NSDateFormatter doesRelativeDateFormatting返回意外的相对日值

时间:2018-01-26 19:54:54

标签: objective-c macos cocoa nsdateformatter macos-high-sierra

在macOS 10.13.3上使用NSDateFormatter时,我将doesRelativeDateFormatting设置为YES时得到的值不正确。我已经看到在格式化程序上使用自定义格式时可能存在相对日期的问题,但我使用的是标准dateStyle& timeStyle次设置。

例如,将纽约市的当前日期与澳大利亚悉尼的日期使用经过适当配置的日期格式化程序而不使用doesRelativeDateFormatting进行比较,日期格式化程序的字符串输出正确显示悉尼的日期为+从纽约市的那一天起1。当我在相同的格式化程序上启用doesRelativeDateFormatting时,悉尼的相对日期错误地返回到同一天(“今天”)。代表这些结果的代码:

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSDate *now = [NSDate date];
        NSDateFormatter *localDateFormatter = [NSDateFormatter new];
        localDateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"America/New_York"];
        localDateFormatter.dateStyle = NSDateFormatterFullStyle;
        localDateFormatter.timeStyle = NSDateFormatterFullStyle;

        NSDateFormatter *remoteDateFormatter = [NSDateFormatter new];
        remoteDateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Australia/Sydney"];
        remoteDateFormatter.dateStyle = NSDateFormatterFullStyle;
        remoteDateFormatter.timeStyle = NSDateFormatterFullStyle;

        NSLog(@"            Now in NYC: %@", [localDateFormatter stringFromDate:now]);
        NSLog(@"         Now in Sydney: %@", [remoteDateFormatter stringFromDate:now]);

        localDateFormatter.doesRelativeDateFormatting = YES;
        remoteDateFormatter.doesRelativeDateFormatting = YES;

        NSLog(@"   Relative now in NYC: %@", [localDateFormatter stringFromDate:now]);
        NSLog(@"Relative now in Sydney: %@", [remoteDateFormatter stringFromDate:now]);
    }
}

输出:

2018-01-26 14:42:28.478 Untitled[40694:1821879]             Now in NYC: Friday, January 26, 2018 at 2:42:28 PM Eastern Standard Time
2018-01-26 14:42:28.479 Untitled[40694:1821879]          Now in Sydney: Saturday, January 27, 2018 at 6:42:28 AM Australian Eastern Daylight Time
2018-01-26 14:42:28.479 Untitled[40694:1821879]    Relative now in NYC: Today at 2:42:28 PM Eastern Standard Time
2018-01-26 14:42:28.479 Untitled[40694:1821879] Relative now in Sydney: Today at 6:42:28 AM Australian Eastern Daylight Time

这是NSDateFormatter中的错误还是我在格式化程序配置中出错?感谢。

2 个答案:

答案 0 :(得分:4)

您的输出是正确的。在世界任何地方打电话给任何人,并询问他们的日期是什么,他们都会说#34;今天"。仅仅因为它在世界两个地方的一周中的某一天并不意味着它不是今天和#34;到处都是。

通过比较两个不同时区的输出,让您自己感到困惑,这两个时区恰好在代码运行的两天内发生。

"亲戚的想法"日期格式是输出是一个相对于"现在"的字符串。在给定的时区。它与任何其他时区无关。在日期格式化程序中设置的任何一个。

答案 1 :(得分:1)

当然,@rmaddy是正确的。启用int main(int argc, char *argv[]) { @autoreleasepool { NSDate *now = [NSDate date]; NSDateFormatter *localDateFormatter = [NSDateFormatter new]; localDateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"America/New_York"]; localDateFormatter.dateStyle = NSDateFormatterFullStyle; localDateFormatter.timeStyle = NSDateFormatterFullStyle; NSDateFormatter *remoteDateFormatter = [NSDateFormatter new]; remoteDateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Australia/Sydney"]; remoteDateFormatter.dateStyle = NSDateFormatterFullStyle; remoteDateFormatter.timeStyle = NSDateFormatterFullStyle; NSLog(@" Now in NYC: %@", [localDateFormatter stringFromDate:now]); NSLog(@" Now in Sydney: %@", [remoteDateFormatter stringFromDate:now]); localDateFormatter.doesRelativeDateFormatting = YES; NSLog(@" Relative now in NYC: %@", [localDateFormatter stringFromDate:now]); NSInteger localSecondsFromGMT = [localDateFormatter.timeZone secondsFromGMTForDate:now]; NSInteger remoteSecondsFromGMT = [remoteDateFormatter.timeZone secondsFromGMTForDate:now]; NSInteger remoteTimeZoneDelta = (remoteSecondsFromGMT - localSecondsFromGMT); NSDate *remoteDate = [now dateByAddingTimeInterval:(NSTimeInterval)remoteTimeZoneDelta]; localDateFormatter.timeStyle = NSDateFormatterNoStyle; remoteDateFormatter.dateStyle = NSDateFormatterNoStyle; NSString *remoteRelativeDate = [localDateFormatter stringFromDate:remoteDate]; NSString *remoteRelativeTime = [remoteDateFormatter stringFromDate:now]; NSLog(@"Relative now in Sydney: %@ at %@", remoteRelativeDate, remoteRelativeTime); } } ,然后将日期与其自己的时区进行比较,将报告“今天”,应该如此。

因此,关键是在远程时区获取日期,然后使用相对于首选(本地)时区的日期并使用本地日期格式化程序的相对日期字符串。修改我的代码以考虑两个时区之间的时差,我通过增量计算本地日期偏移量并使用本地日期格式化程序获取日期字符串(仍然使用时间字符串的远程日期格式化程序,因为它包含时区名称)。

这并不完美,因为我没有正确地对字符串进行本地化(' at'正在手动插入而没有本地化)但是这个修改过的代码基本上得到的结果是我&# 39;我看:

2018-01-27 16:08:12.856 Untitled[95771:3146343]             Now in NYC: Saturday, January 27, 2018 at 4:08:12 PM Eastern Standard Time
2018-01-27 16:08:12.857 Untitled[95771:3146343]          Now in Sydney: Sunday, January 28, 2018 at 8:08:12 AM Australian Eastern Daylight Time
2018-01-27 16:08:12.857 Untitled[95771:3146343]    Relative now in NYC: Today at 4:08:12 PM Eastern Standard Time
2018-01-27 16:08:12.857 Untitled[95771:3146343] Relative now in Sydney: Tomorrow at 8:08:12 AM Australian Eastern Daylight Time

输出:

Auth::user(); 

这有点不雅,但它适合我目前的需要。