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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容