时间处理是个很头疼的问题,为啥呢?因为世界各地有时区差异,虽然苹果做了一套非常完善的时间处理机制,但若不细心研究一番,还是很容易踩坑。我们不论是从系统直接取的时间,还是与后端交互得到的时间,基本都是UTC时间,什么是UTC呢?让我们回到初中......
GMT & UTC
说UTC前先说一下它的前身:GMT,即格林尼治标准时间,也就是“世界时”。GMT时是指:正午时太阳横穿格林尼治子午线(本初子午线)的时间。但由于地球自转不均匀不规则,导致GMT不精确,现在已经不再作为世界标准时间使用。
那么就有它的升级版本,UTC,即“协调世界时”。UTC是以原子时秒长为基础,在时刻上尽量接近于GMT的一种时间计量系统。为确保UTC与GMT相差不会超过0.9秒,在有需要的情况下会在UTC内加上正或负闰秒。UTC现在作为世界标准时间使用。目前计算机时间都是用UTC
时区
地球自西向东旋转,东边比西边先看到太阳,东边的时间也比西边的早。为了统一世界的时间,1884年的国际经度会议规规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为零时区(GMT+00),东1-12区,西1-12区,中国北京处于东8区(GMT+08)。
若英国时间为6点整,则GMT时间为6点整,则北京时间为14点整。
由于:UTC与GMT基本上等同(误差不超过0.9秒),所以UTC时间的换算方法跟GMT一样。
有了以上的知识储备,再来理解苹果的时间处理就很简单了
获取当前时间
最简单的获取方法是:
NSDate *nowTime = [NSDate date];
但这样拿到的是零时区的时间,而我大天朝的时区在东八区,那么我们需要将这个时间处理一下。
- (NSString *)getNowDateToString{
NSDate *date = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
//核心是这里,设置时区,不设置的话,NSDateFormatter会自动设置为手机当前的时区,为了保持一致性最好写,这样不管
//我们的手机是在哪里,打印出来的时间都是东八区的时间
dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
//dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Tokyo"];//东九区时间
//dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];//零区时间
//dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];//零区时间,和GMT一样
[dateFormat setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
NSString *dateString = [dateFormat stringFromDate:date];
return dateString;
}
另一种情况,是从接口获得时间,一般情况下,接口返回给我们的时间是不带时区的
比如:
2020-12-23 18:47:28
当我们用NSDateFormatter转为NSDate时,如果不指定TimeZone,那么默认是UTC零时区,所以转换出来的结果会比接口拿到的少8小时,就是:
2020-12-23 10:47:28
那么同样的思路,这么写可以解决:
dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
相当于直接指定为东八区时间。
xcode在这里有个坑,
我这么写:
//转换代码
- (NSDate *)stringToNSDate:(NSString *)dateString{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
return [formatter dateFromString:dateString];
}
当我鼠标移到 date 变量上取值的时候,取到的是比目标时间少8小时的,燃鹅,打印的值:
Wed Nov 11 10:20:30 2020
我他妈的也是服了,刚开始没打印,怎么调都奇怪,还好老子打印了一下 = =
好了,今天就写这么多,最后贴个常用的转换代码
//NSString时间 转 NSDate格式
- (NSDate *)stringToNSDate:(NSString *)dateString{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
return [formatter dateFromString:dateString];
}
//NSDate时间 转 NSString格式
- (NSString *)dateToString:(NSDate *)date{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
[dateFormat setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
NSString *dateString = [dateFormat stringFromDate:date];
return dateString;
}