【发布时间】:2019-05-16 04:25:34
【问题描述】:
我已将我的手机(实际设备,而非模拟器)配置为位于英国伦敦,即 GMT。
当我使用localTimeZone 在NSCalendar 上设置时区时,与使用[NSTimeZone timeZoneWithAbbreviation:@"GMT"] 设置时区相比,我的时间减少了1 分15 秒。如果我的时区已经设置为 GMT,两者不应该给我相同的结果吗?
我注意到的另一件事是,如果我设置断点,则使用localTimeZone 创建的NSDate 通过断点检查会关闭 1 分 15 秒,但 NSLog 会打印正确的时间(断点显示:0000-12 -30 09:01:15 UTC 但 NSLog 打印 Sat Dec 30 09:00:00 0000):
但是当我使用[NSTimeZone timeZoneWithAbbreviation:@"GMT"] 时,断点会显示正确的时间,但NSLog 会在 1 分 15 秒后打印出错误的时间(断点显示:0000-12-30 09:00:00 UTC 但是NSLog 打印 Sat Dec 30 08:58:45 0000):
这是我的代码以及旁边的 cmets 中的断点和 NSLog 输出:
NSLog(@"Timezone: %@",[NSTimeZone localTimeZone]);//Timezone: Local Time Zone (Europe/London (GMT) offset 0)
NSLocale *locale = [NSLocale currentLocale];
NSCalendar *myCalendar = [NSCalendar currentCalendar];
[myCalendar setLocale:locale];
[myCalendar setTimeZone:[NSTimeZone localTimeZone]];
NSLog(@"TZ: %@",myCalendar.timeZone);//TZ: Local Time Zone (Europe/London (GMT) offset 0)
NSDateFormatter *timeFormatter = [NSDateFormatter new];
[timeFormatter setDateFormat:@"h:mm a"];
[timeFormatter setLocale:locale];
[timeFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents* dateComps = [myCalendar components:NSCalendarUnitHour|NSCalendarUnitMinute fromDate:[timeFormatter dateFromString:@"9:00 AM"]];
NSDate *myDate1 = [myCalendar dateFromComponents:dateComps];//Breakpoint shows: 0000-12-30 09:01:15 UTC
NSLog(@"myDate1: %@",myDate1); // myDate1: Sat Dec 30 09:00:00 0000
//----------------Explicitly specified timeZoneWithAbbreviation GMT:
NSCalendar *myCalendarExplicitGMT = [NSCalendar currentCalendar];
[myCalendarExplicitGMT setLocale:locale];
[myCalendarExplicitGMT setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSLog(@"TZ: %@",myCalendarExplicitGMT.timeZone);//TZ: GMT (GMT) offset 0
NSDateComponents* dateCompsUsingExplicitGMT = [myCalendarExplicitGMT components:NSCalendarUnitHour|NSCalendarUnitMinute fromDate:[timeFormatter dateFromString:@"9:00 AM"]];
NSDate *myDate2 = [myCalendarExplicitGMT dateFromComponents:dateCompsUsingExplicitGMT];//Breakpoint shows: 0000-12-30 09:00:00 UTC
NSLog(@"myDate2: %@",myDate2); // myDate2: Sat Dec 30 08:58:45 0000
【问题讨论】:
-
如果您使用 @"UTC" 时区而不是 @"GMT" 会发生什么?除了闰秒之外,它们应该是相同的,我认为它被忽略了。我认为到目前为止已经有 37 个闰秒,这大约是你的差异的一半,所以除非它被调整两次(并且一次太多),否则不确定这是否能解释它。但这似乎很弱。
-
@CarlLindberg 刚刚测试了 UTC,它打印的内容与 GMT (08:58:45) 相同。用于打印时区的 NSLog 打印“GMT”而不是 UTC。我相信在幕后 UTC 和 GMT 是一样的。
-
它们在技术上是不同的,但它们应该导致显示相同的时间。只是在确定。另一方面,它似乎显示的是零年(公元前 1 年)。可能会有一些奇怪的地方。也许尝试将 NSDateComponents 中的年份设置为更现代一点?
-
@CarlLindberg 如果我将组件设置为
NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[timeFormatter dateFromString:@"01-01-2000 9:00 AM"]并将格式设置为@"MM-dd-yyyy h:mm a",那么它似乎确实匹配。如果我最初要求日期组件只使用小时和分钟,为什么有必要? -
它正在转换为 NSDate,这是一个完全指定的时刻,因此您需要提供年/月/日值等以从组件值中获取 NSDate - 即它总是需要完整的日历转换来创建 NSDate,如果没有指定,它将使用默认值(否则必须返回 nil)。而且我想一旦你到了 BC 年,时区的实现就会有细微的差别。不好的部分是 NSDateFormatter 不能直接在 NSDateComponents 上操作,需要 NSDate 步骤,你最好使用当前年份。
标签: ios nsdate nsdateformatter nscalendar nsdatecomponents