某日发现 DateTools 的 weekday 方法在不同 iOS 上计算出的结果不一样的问题。具体表现为:在 iOS 10 上计算出的结果比 iOS 12 上的结果少一天。比如同样是 2019-09-23,iOS 10 上计算结果为 1,而 iOS 12 上计算结果为 2。
跟踪代码发现,weekday 方法中调用了 [self componentForDate:self type:DTDateComponentWeekday calendar:nil]; 一句。
这里的 calendar 参数为 nil 表明将使用默认日历,而默认日历的 timezone 默认将使用本地时区。
但是,在 iOS 11 之前,NSTimeZone 无法正确获取系统设置的时区!因而导致计算出的结果少了一天。
分别在 iOS 11-12 和 iOS 10-10.3 下调用 NSTimeZone 的 defaultTimeZone、localTimeZone 和 systemTimeZone,以及 [NSCalendar currentCalendar].timeZone,发现后者无法正确获取到系统设置的当前地区。
以下测试在模拟器上进行,测试前都将地区设置为 China。
这是 iOS 11.4-12.4 的测试结果:
iOS 11.4 - 12.4
------------------------------------
(lldb) po [NSTimeZone defaultTimeZone]
Asia/Shanghai (GMT+8) offset 28800
(lldb) po [NSTimeZone localTimeZone]
Local Time Zone (Asia/Shanghai (GMT+8) offset 28800)
(lldb) po [NSTimeZone systemTimeZone]
Asia/Shanghai (GMT+8) offset 28800
(lldb) po [NSCalendar currentCalendar].timeZone
Asia/Shanghai (GMT+8) offset 28800
上面的结果显示,iOS 11.4 - 12.4 上,通过上述 API,能够正确获取到系统设置的时区(中国 +8 区)。
iOS 10-10.31 的测试结果如下:
iOS 10 - 10.31
------------------------------------
(lldb) po [NSTimeZone defaultTimeZone]
GMT (GMT) offset 0
(lldb) po [NSTimeZone localTimeZone]
Local Time Zone (GMT (GMT) offset 0)
(lldb) po [NSTimeZone systemTimeZone]
GMT (GMT) offset 0
(lldb) po [NSCalendar currentCalendar].timeZone
GMT (GMT) offset 0
上面的结果显示,iOS 10-10.31 上,无法正确获取到的系统当前时区,都会返回 GMT。
用 weekdayWithCalandar 方法取代 weekday 方法。
NSCalendar* cal = [NSCalendar currentCalendar];
cal.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
NSInteger w = [baseDate weekdayWithCalendar:cal];