【问题标题】:Struggling with NSDate, formats and timezones与 NSDate、格式和时区作斗争
【发布时间】:2011-12-13 22:30:07
【问题描述】:

交易是我想要 1978 年 6 月 18 日的 NSDate 表示。 我试图像这样初始化 NSDate

dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
self.dateFormatter.timeStyle = NSDateFormatterNoStyle;
self.startDate = [dateFormatter dateFromString:@"19/06/78"];
NSLog(@"%@", self.startDate);

当 iPhone 在国际设置中设置为丹麦语时,这会产生正确的日期。 它不适用于设置为英语/美国设置的 iPhone。

请注意额外的一天 (19),因为丹麦是 GMT +1,我认为 NSDate 默认为 23:00:00。这表明我没有按预期工作。

我希望上述日期 (18/06/1978) 代表一个 NSDate 对象,而不考虑设备上的时区、区域设置和国际设置。

如何实现?

编辑:

所以 Ole Begemann 的回答似乎解决了我的问题。他的解决方案确实在美国国际设置和欧洲国际设置的设备上创建了正确的日期。 但是当 Apple 应该审查应用程序时,创建的日期是 1978 年 6 月 17 日。这是有道理的,因为我将时区设置为 GMT +0000。而库比蒂诺就像格林威治标准时间 -0007 左右。 所以这会提前一天。

所以纠正我的问题:我想要 18-06-1978,无论设备在什么区域、时区或设置明智。

我要做的是设置开始日期 1978 年 6 月 18 日及以后在我的应用程序中将日期呈现为格式为“780618”(yyMMdd) 的字符串,无论设备的时区或位置如何。它总是必须是“780618”,因为这是我的应用程序的关键开始日期。

所以我可能把问题处理错了。而不是试图在任何地方强制使用相同的日期,我可能应该接受时区的东西并尝试配置 NSDateFormatter 以输出正确的日期。

所以基本上:我想要的是 NSDate 实例,它在任何地方都格式化为“780618”——在任何时区,任何国际设备设置。

如何做到这一点?

【问题讨论】:

    标签: iphone ipad nsdate nsdateformatter


    【解决方案1】:

    我希望上述日期 (18/06/1978) 代表一个 NSDate 对象,而不考虑设备上的时区、区域设置和国际设置。

    这对NSDate 来说毫无意义。 NSDate 始终代表一个时间点,因此根据定义,它包括一个时间和该时间所在的时区(或者更准确地说,它以 GMT 存储时间;时间仅转换为另一个时区用于显示目的)。如果您只想要日期,则必须对时间做出自己的定义,例如以格林威治标准时间午夜的时间存储这些日期。

    以编程方式设置日期时,您必须始终设置时区,如果您使用日期格式化程序,请设置格式化程序的区域设置和日历。这可确保您的代码独立于用户/设备的区域设置。

    我会这样做:

    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    [dateComponents setYear:1978];
    [dateComponents setMonth:6];
    [dateComponents setDay:18];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDate *date = [calendar dateFromComponents:dateComponents];
    NSLog(@"%@", date);
    

    【讨论】:

    • 工作就像一个魅力。尝试了其他答案,但没有任何效果。要么保持不变,要么 NSDate 默认为 2001 年 1 月 1 日。(我相信 DateFormatter 返回 nil 的结果)。谢谢你的想法。
    • 我是这么想的。我的应用程序被 Apple 拒绝,因为没有内容。 (该应用程序使用日期来获取内容。)我已根据 Apple 的回复编辑了我的问题。
    • 我很确定我不了解 NSDate。所以我的问题可能是我没有在所有日历格式化程序上设置时区?我会尝试将所有格式化程序设置为 GMT。但是我如何验证它是否有效?在模拟器上设置时区是不可能的。如何从另一个时区“模拟”测试应用程序?
    • 我已将我所有的 NSDateFOrmatters 配置为 GMT+0000。通过将我的 ipad 设置为不同的时区对其进行了测试,一切似乎都正常。让我们看看 Apple 怎么说 :-) 非常感谢 Ole 的帮助。
    • 正如我所说,如果您还没有设置格式化程序的日历,它仍然不适用于使用与西方日历不同的日历的人。
    【解决方案2】:

    你可以这样做:

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    
    // Set the locale to en_US_POSIX. This makes the date formatter respect
    // the format string regardless of the user's locale.
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    [formatter setLocale:locale];
    [locale release];
    
    // We want the date in the user's current time zone.
    [formatter setTimeZone:[NSTimeZone localTimeZone]];
    
    [formatter setDateFormat:@"dd/MM/yy"];
    
    NSDate *date = [formatter dateFromString:@"18/06/78"];
    
    [formatter release];
    
    NSLog(@"%@", date);
    

    日期显示为这样1978-06-17 23:00:00 +0000 是因为NSDate 的描述返回格林威治标准时间的日期。 GMT+1 的 1978 年 6 月 17 日 23:00 是 1978 年 6 月 18 日 00:00。

    【讨论】:

    • 您的建议使 dateformatter 返回 nil;但是您对 NSDate 描述的解释是有道理的。
    • @Morten:我不会将 NSDate 解释为“因为 NSDate 的描述返回格林威治标准时间的日期”。我已经在本地更正了仍然显示 +0000 的日期。所以,实际上,它是一个尾随的垃圾。许多人重复说 NSDate 没有时区是用词不当。鉴于描述显示它,它拥有它。 Apple 可以通过允许我们为编码世界提供一项巨大的服务,我们都可以重新开始工作:NSDate *localDate = [NSDate localDate] 或 NSDate *localDate = [myUTCDate localDate] .. 看看这个:(lldb) po myLocalDate 2015-05-02 16:44:53 -0800 (lldb)
    猜你喜欢
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 2012-12-12
    相关资源
    最近更新 更多