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

时间:2012-10-16 20:09:20

标签: objective-c ios6 nsdate nsdateformatter julian

尝试在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);
}

您将获得以下输出:

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo

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

2 个答案:

答案 0 :(得分: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);
            }
        }
    }
}

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

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Brazil/East

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

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

答案 1 :(得分: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提交了一个错误。