前言
- 1.该类(NSISO8601DateFormatter)是在iOS 10才出现的。
- 2.该类完美的处理了时间问题,即使你的APP涉及国外用户,只要你们开发团队在时间格式上都遵守ISO8601格式,那么你就再也不用担心时间出错了。当然,你们也可以使用时间戳。
常用方法
1.NSDte转字符串:- stringFromDate:
使用方法请看 属性介绍 >> 1.timeZone2.字符串转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);