为什么NSDateFormatter会为这4个时区返回nil日期?

lpa*_*lpa 42 objective-c nsdate nsdateformatter julian-date ios6

尝试在iOS6中运行它(尚未测试iOS6之前):

NSDateFormatter *julianDayDateFormatter = nil;
julianDayDateFormatter = [[NSDateFormatter alloc] init];
[julianDayDateFormatter setDateFormat:@"g"];

for (NSString *timeZone in [NSTimeZone knownTimeZoneNames]) {
    julianDayDateFormatter.timeZone = [NSTimeZone timeZoneWithName: timeZone];
    NSDate *date = [julianDayDateFormatter dateFromString:[NSString stringWithFormat:@"%d", 2475213]];
    if (date == nil)
        NSLog(@"timeZone = %@", timeZone);
}
Run Code Online (Sandbox Code Playgroud)

并得到以下输出:

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释为什么这四个时区的行为是这样的,NSDateFormatter设置为朱利安日数?所有其他时区使NSDateFormatter返回实际的NSDates.

Jon*_*eet 61

我有一个怀疑.只是怀疑,但相当强烈.

该值代表2064年10月19日.巴西时区从当地午夜开始观察夏令时- 那是他们的时钟前进的时间,因此午夜本身不存在.10月19日是其中一个转变.

这是一些使用Noda Time的示例代码,我的.NET日期/时间API.它会检查它所知道的每个时区的当天开始时间是否实际是午夜:

using System;
using NodaTime;

class Test
{
    static void Main()
    {
        var localDate = new LocalDate(2064, 10, 19);
        var provider = DateTimeZoneProviders.Tzdb;
        foreach (var id in provider.Ids)
        {
            var zone = provider[id];
            var startOfDay = zone.AtStartOfDay(localDate).LocalDateTime.TimeOfDay;
            if (startOfDay != LocalTime.Midnight)
            {
                Console.WriteLine(id);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生了一个非常相似的列表:

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Brazil/East
Run Code Online (Sandbox Code Playgroud)

我怀疑巴西/东方可能是America/Sao_Paolo的别名,这就是为什么它不在你的名单上.

无论如何,为了回到你的朱利安日问题 - 我怀疑格式化程序总是希望返回NSDate *当地午夜时分.2064年10月19日在那些时区不存在 ......因此它返回零.就个人而言,我建议它应该返回1am值,但是嘿......


lpa*_*lpa 16

致Jon Skeet让我走上正轨.但是,我只是想在iOS环境中澄清他的答案.

当您要求NSDateFormatter将朱利安日数转换为NSDate时,您只能在要解析的字符串中指定整数(通常可以指定当天的小时/分钟/秒的小数部分).因为Apple在午夜划定了朱利安的日子(而不是天文学中午,请在这里阅读更多内容:http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table)并且有些午夜根本不存在(感谢指出这一点) @JonSkeet)NSDateFormatter识别该特定时间点在该时区中不存在并返回nil.

为了记录,iOS5不是这样的,我同意Jon Skeet,NSDateFormatter应该返回一个调整为DST而不是nil的NSDate,因为事实上这个特定的朱利安日存在!我向Apple提交了一个错误.