IOS时间本地化处理

2,862 阅读4分钟

时间处理是个很头疼的问题,为啥呢?因为世界各地有时区差异,虽然苹果做了一套非常完善的时间处理机制,但若不细心研究一番,还是很容易踩坑。我们不论是从系统直接取的时间,还是与后端交互得到的时间,基本都是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;
}