42

尝试在 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。

4

2 回答 2

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 日不存在这种情况……因此它返回 nil。我个人建议它应该返回 1am 值,但是嘿......

于 2012-10-16T20:29:02.557 回答
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提交了一个错误。

于 2012-10-17T09:01:31.440 回答