【问题标题】:Why does NSDateFormatter return nil date for these 4 time zones?为什么 NSDateFormatter 为这 4 个时区返回 nil 日期?
【发布时间】:2012-10-07 00:31:37
【问题描述】:

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

【问题讨论】:

  • 这是一个可靠的问题,但这里明显的 Jon Skeet 效应绝对令人讨厌。
  • @JoshCaswell:这很棘手。我总是对在推特上发布这类事情感到紧张。这肯定会扭曲选票——但我想引起人们对我认为他们会觉得有趣的事情的注意。至少我的答案的投票与代表无关......

标签: objective-c ios6 nsdate nsdateformatter julian-date


【解决方案1】:

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

该值表示 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 值,但是嘿...

【讨论】:

  • 谢谢。你把我带到了正确的轨道上。这肯定与过渡到夏令时有关。记录一下:iOS5 不这样做,它总是返回一个 NSDate。我用 Apple 填了一个 bug。
  • @lpa:出于兴趣,这些时区返回什么值?如果它返回一个本地时间为午夜的值,那是另一种方式的错误?
  • “这些时区返回什么值?”在 iOS5 中?
  • @lpa:是的,完全正确。那些日期不存在当地午夜 - 返回凌晨 1 点是有意义的,因为那是当地一天的开始。
  • 抱歉回复晚了。 iOS5.0 返回凌晨 1 点,但巴西返回凌晨 12 点。在 iOS5.1 中,它返回所有时区的凌晨 1 点。
【解决方案2】:

感谢 Jon Skeet 让我走上了正轨。但是,我只是想在 iOS 上下文中澄清他的答案。

当您要求 NSDateFormatter 将儒略日数转换为 NSDate 时,您只能在要解析的字符串中指定整数(通常可以指定一天中的小时/分钟/秒的小数部分)。 因为 Apple 在午夜划分朱利安日(与天文学中的中午相反,请在此处阅读更多信息:http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table)并且某些午夜根本不存在(感谢@JonSkeet 指出这一点)NSDateFormatter 确定该特定时间点不存在' t 存在于该时区并返回 nil。

作为记录,iOS5 的行为并非如此,我同意 Jon Skeet 的观点,即 NSDateFormatter 应该返回为 DST 而不是 nil 调整的 NSDate,因为那个特定的朱利安日实际上存在!我向 Apple 提交了一个错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多