iOS-NSISO8601DateFormatter

前言

  • 1.该类(NSISO8601DateFormatter)是在iOS 10才出现的。
  • 2.该类完美的处理了时间问题,即使你的APP涉及国外用户,只要你们开发团队在时间格式上都遵守ISO8601格式,那么你就再也不用担心时间出错了。当然,你们也可以使用时间戳

常用方法

  • 1.NSDte转字符串:- stringFromDate:

    使用方法请看 属性介绍 >> 1.timeZone

  • 2.字符串转NSDate:- dateFromString:

    在使用该方法的时候,一定要注意格式问题,目前我见过的格式有:

第一种:yyyy-MM-dd'T'HH:mm:ssZZZZZ(例如:2017-06-08T12:00:10+08:00)

第二种:yyyy-MM-dd'T'HH:mm:ss.SZZZZZ(时间带毫秒,例如:2017-06-08T12:00:10.559+08:00,其中.559就是毫秒。)

注意:在处理第二种格式的时候,需要想办法去掉毫秒,否则在使用- dateFromString时,会出问题。心细的朋友会发现,- stringFromDate转出来的字符串中,都是不带毫秒的。

下面笔者给大家介绍下ISO8601时间字符串转NSDate,其实很简单,直接上代码

    NSISO8601DateFormatter *ISO8601DateFormatter = [[NSISO8601DateFormatter alloc] init];
    
    NSDate *ISO8601Date = [ISO8601DateFormatter dateFromString:@"2017-06-08T12:00:00+08:00"];
    
    NSLog(@"ISO8601Date = %@", ISO8601Date);
    
    // 注意:美国芝加哥时间(西5区,比中国慢13小时,比0市区慢5个小时)
    ISO8601Date = [ISO8601DateFormatter dateFromString:@"2017-06-08T12:00:00-05:00"];
    
    NSLog(@"ISO8601Date = %@", ISO8601Date);

------------打印结果---------------------
ISO8601Date = 2017-06-08 04:00:00 +0000 // 注释:东8区时间转成了0市区的时间了
ISO8601Date = 2017-06-08 17:00:00 +0000 // 注释:西5区时间转成了0市区的时间了

小结:使用- dateFromString方法时,api内部都会将时间统一转成0时区的时间。


属性介绍

  • 1.timeZone
    小结:timeZone设置之后,获取到的时间字符串中会带有时区。另外,目前笔者认为,timeZone值在NSDate转字符串时有作用。
    NSISO8601DateFormatter *ISO8601DateFormatter = [[NSISO8601DateFormatter alloc] init];
    
    // 格林尼治时间(0时区时间)
    NSDate *GMTDate = [NSDate date];
    // 获取时区名称
    NSLog(@"%@", [NSTimeZone knownTimeZoneNames]);
    
    // 不设置时区 注意:不设置时区,默认是0时区
    NSString *ISO8601DateString = [ISO8601DateFormatter stringFromDate:GMTDate];
    NSLog(@"ISO8601DateString = %@", ISO8601DateString);
    
    // 将系统时区设置为当前时区
    ISO8601DateFormatter.timeZone = [NSTimeZone systemTimeZone];
    ISO8601DateString = [ISO8601DateFormatter stringFromDate:GMTDate];
    NSLog(@"ISO8601DateString = %@", ISO8601DateString);
    
    // 设置美国芝加哥时区 注意:美国芝加哥在西5区,比中国慢13小时
    ISO8601DateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"America/Chicago"];
    
    ISO8601DateString = [ISO8601DateFormatter stringFromDate:GMTDate];
    
    NSLog(@"ISO8601DateString = %@", ISO8601DateString);

-------------打印结果如下---------------------
ISO8601DateString = 2017-06-09T03:22:48Z // 注释:0时区时间
ISO8601DateString = 2017-06-09T11:22:48+08:00 // 注释:中国时间
ISO8601DateString = 2017-06-08T22:22:48-05:00 // 注释:芝加哥时间
---------------小结-------------------
其实设不设置时区都是没关系,只不过设置时区,转出来的字符串看起来比较直观。你一看就知道这个日子是从哪个时区获取得到的。实际上上面三个时间都是同一个时间。只是因为地方不同,所以有时差

补充(2017-06-10)

给需要的朋友们补充点东西,有更好方法的朋友,可以在评论下方和我分享哦!

  • 1.带毫秒的ISO8601格式的日期字符串转NSDate
// 带毫秒ISO8601日期字符串转NSDate
NSString *dateString = @"2017-06-08T10:00:00.123+08:00";

NSInteger systemDevice = [[[[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."] firstObject] integerValue];

///ISO8601格式的日期字符串转NSDate
    //系统适配
    if (systemDevice >= 10) {// iOS系统版本 >= 10.0
        
        NSISO8601DateFormatter *ISO8601DateFormatter = [[NSISO8601DateFormatter alloc] init];
        
        // 去掉毫秒数,否则string转date会失败
        if ([dateString containsString:@"."]) {
            
            NSRange pointRang = [dateString rangeOfString:@"."];
            
            NSRange subStrinEndRang = NSMakeRange(0, 0);
            
            if ([dateString containsString:@"+"]) {
                subStrinEndRang = [dateString rangeOfString:@"+"];
            }else if ([dateString localizedCaseInsensitiveContainsString:@"z"]) {// 不区分大小写
                subStrinEndRang = [dateString rangeOfString:@"z" options:NSCaseInsensitiveSearch];// 查找时也不区分大小写
            }else if ([dateString containsString:@"-"]) {// 注意:这种情况要放最后判断,因为年月日之间就是用'-'分开的
                subStrinEndRang = [dateString rangeOfString:@"-" options:NSBackwardsSearch];
            }else {
                NSAssert(dateString == nil, @"ISO8601String中没有+-z字符");
            }
            
            NSString *replaceString = [dateString substringWithRange:NSMakeRange(pointRang.location, subStrinEndRang.location - pointRang.location)];
            
            dateString = [dateString stringByReplacingOccurrencesOfString:replaceString withString:@""];
            
            NSLog(@"处理之后的字符串dateString = %@", dateString);
        }
        
        NSDate *date = [ISO8601DateFormatter dateFromString:dateString];
        
        return date;
        
    }else {// iOS 10.0以下适配
        
        NSDateFormatter *ISO8601DateFormatter = [[NSDateFormatter alloc] init];
        
        // 格式适配。带毫秒的格式和不带毫秒的格式
        if ([dateString containsString:@"."]) {
            ISO8601DateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SZZZZZ";
        }else {
            ISO8601DateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZZZZZ";
        }
        
        NSDate *date = [dateFormatter dateFromString:dateString];
        
        return date;
    }

2.ISO8601格式日期字符串使用
服务器给的ISO8601格式日期字符串是不是拿到就能直接使用呢?当然不是,还得转成当前时区的时间再使用。代码如下:

/**
     前言
     假设这是在iOS10.0及以上系统运行的代码
     如果在iOS10.0以下系统运行这段代码,ISO8601DateFormatter对象等于nil。因为NSISO8601DateFormatter类iOS10.0才出现的。
     */
    
    // 假设这是服务器给自己的时间 显然这是0时区的时间,我们在中国要显示这个时间时,\
    肯定不是显示2017-06-08 12:00:00,而是2017-06-08 20:00:00。因为我国时间比0时区时间要快8个小时。
    NSString *ISO8601DateString = @"2017-06-08T12:00:00Z";
    
    // 第一步:将字ISO8601格式日期字符串转NSDate
    NSISO8601DateFormatter *ISO8601DateFormatter = [[NSISO8601DateFormatter alloc] init];
    
    NSDate *date = [ISO8601DateFormatter dateFromString:ISO8601DateString];
    
    // 第二步:将date转成当地时区的时间字符串
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZ"];
    
    // 这个字符串里面的时间,我们就拿出来显示了
    NSString *dateString = [dateFormatter stringFromDate:date];
    
    NSLog(@"dateString = %@", dateString);

你可能感兴趣的:(iOS-NSISO8601DateFormatter)