关于NSDate,NSDateFormatter,NSTimeZone的一些通俗理解

xiaoxiao2021-02-28  80

基础概念

1.GMT 0:00 格林威治标准时间; UTC +00:00 校准的全球时间; CCD +08:00 中国标准时间 2.iOS中的时间类NSDate中存储的时间,都是相对于GMT的,我们使用NSDate 时(NSDate必须是0时区的,UTC格式的),会根据App设置的当前时区设置返回 与时区对应的数据。 3.iOS中的时区表示方法:GMT+0800 GMT-0800。(+:东区 -:西区 08:小 时数 00:分钟数)。 GMT+0830就是指比GMT早8小时外加30分钟的时区。 4.世界标准时间,国际协调时间,简称UTC。不属于任意时区 5.系统认为NSDate是0时区的,NSString是东八区的

简单说下个人的理解 根据时区可以看到,我们在东八区,时间点比国际标准时间快八小时,而LA在在西7区,时间慢7小时,因此,同一时间下,你切换手机坐标,你获取的时间戳美国比中国的大,因为时间戳的计算都是根据0时区来算的,中国的要减去,美国自然要加上了,有个简单的例子,如果你默认NSDate TimeZone下,你切换计算时间戳是没有问题,但是如果你用东八区的时间戳去使用,肯定比实际上多出来八小时,这个时候如果要上传给服务器,那就尴尬了哈。。。如果你手动切换时区,记得算好时间戳。下面会给例子,有个很重要的思想就是,显示的时候用NSString,但是内部涉及到计算,比较,时间戳的问题,都是要NSDate,这样保证计算出来的东西肯定不会错

代码示例一:不同时区之间的时间转换

// 获取usr/share/zoneinfo目录下所有已知的时区 NSArray *arr = [NSTimeZone knownTimeZoneNames]; // 获取所有时区的缩写 NSDictionary *dict = [NSTimeZone abbreviationDictionary]; NSLog(@"%@",dict); NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; NSString *timeStr = @"2017-05-10"; NSDate *currentDate = [dateFormatter dateFromString:timeStr]; NSLog(@"需要格式化的时区--->%@,格式后的Date--->%@",dateFormatter.timeZone,currentDate); [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSDate *currentDate1 = [dateFormatter dateFromString:timeStr]; NSLog(@"需要格式化的时区--->%@,格式后的Date--->%@",dateFormatter.timeZone,currentDate1); [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/Los_Angeles"]]; NSDate *currentDate2 = [dateFormatter dateFromString:timeStr]; NSLog(@"需要格式化的时区--->%@,格式后的Date--->%@",dateFormatter.timeZone,currentDate2); /* 2017-05-05 14:32:13.893 NSData[10583:4643459] 需要格式化的时区--->Asia/Shanghai (GMT+8) offset 28800,格式后的Date--->2017-05-09 16:00:00 +0000 个人理解: 时间信息都是针对于GMT标准时区来的,那么NSDate是根据当前设置的时区来进行计算的,那么例如上面的时间,默认是上海东八区的话就是向前移动8小时就是0时区的时间,所以打印出来的就是少8小时 OK,我们来设置下dateFormatter的时区为GMT和PDT(美国洛杉矶西七区),也就是NSDate默认为你就在标准时区的坐标下,你给出来的时间根本不需要进行时区的转换,直接显示出来接即可,但是PDT的情况下是西区,时间比0区小,因此要加上7小时 2017-05-05 15:01:52.121 NSData[10996:4659886] 需要格式化的时区--->GMT (GMT) offset 0,格式后的Date--->2017-05-10 00:00:00 +0000 2017-05-05 15:01:52.124 NSData[10996:4659886] 需要格式化的时区--->America/Los_Angeles (PDT) offset -25200 (Daylight),格式后的Date--->2017-05-10 07:00:00 +0000 */

这一坨简单的代码和上面的图一结合,应该非常清楚的能明白 首先,NSDate是计算0时区的时间,默认情况下NSDateFormmater是获取当前手机设置的时区(咱们的是东八区),因此,这就解释了默认情况下你转换的时间NSDate比字符串少了八个小时,但是如果你手动表示,你就在GMT,那就不需要转换了,直接显示字符串时间,但是如果你说你在LA,西区,自然要加上7小时了

代码示例二:String和Date转换

// 最简单的NSDate和NSString的转换 NSString *timeStr1 = @"2017-5-20"; NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init]; [dateFormatter1 setDateFormat:@"yyyy-MM-dd"]; NSDate *date1 = [dateFormatter1 dateFromString:timeStr1]; // 加上了这句话 转换的时候无需再算上时区,直接转换 // [dateFormatter1 setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSString *resultStr = [dateFormatter1 stringFromDate:date1]; NSLog(@"%@,%@",date1,resultStr);

这简单例子告诉我们,默认不设置时区的情况下,如果你在天朝东八区,你用的时间字符串,转换成NSDate(无论如何算出来的都是GMT/UTC国际标准时间0时期的时间)的时候会减去八小时,但是转换成NSString的时候又会转换成GMT标准时间下的(加上了八小时当前时期东八区)字符串,系统认为NSDate是0时区的,NSString是东八区的

代码示例三:反面教材,可以用TimeZone进行时区切换操作更好

NSDate *date3 = [NSDate date]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间1%@",date3); NSDate *date4 = [NSDate dateWithTimeIntervalSinceNow:0]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间2%@",date4); NSDate *date5 = [NSDate dateWithTimeIntervalSinceNow:8*60*60]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间3加上今天此刻时间%@",date5); NSDate *date6 = [NSDate dateWithTimeIntervalSinceNow:(8-24)*60*60]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间3昨天此刻时间%@",date6); NSDate *date7 = [NSDate dateWithTimeIntervalSinceNow:(8+24)*60*60]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间3明天此刻时间%@",date7); // 参数1比参数2小返回的是负数 NSTimeInterval timeIntervel = [date6 timeIntervalSinceDate:date7]; NSLog(@"NSDate(0时区标准时间 所在东八区,要减去八小时)----当前时间3昨天和明天时间间隔%.f",timeIntervel);

代码示例四:时间戳秒数转换NSDate注意点

/* 不转换的时候NSDate出来的肯定是没有问题的0时区的时间 */ NSDate *date8 = [NSDate date]; NSTimeInterval time8 = [date8 timeIntervalSince1970]; NSLog(@"%.f",time8); NSDate *date9 = [NSDate dateWithTimeIntervalSince1970:1493968897]; NSLog(@"%@",date9); // 这个例子只是说明,如果你用东八区的时间,然后你又手动修改了你当前的时区,你该到了GMT 0时区,这个时候的时间戳肯定比0时区多出八小时了, // 你只要明白,正确的时间戳都针对GMT 0时区的国际标准时间为准的,如果前后台需要涉及到时间上传交互,你如果你手动切换了时区,需要注意时区 NSDate *date10 = [NSDate date]; NSDateFormatter *fotmatter10 = [[NSDateFormatter alloc] init]; [fotmatter10 setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSString *string10 = [fotmatter10 stringFromDate:date10]; [fotmatter10 setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSDate *date100 = [fotmatter10 dateFromString:string10]; NSTimeInterval time10 = [date100 timeIntervalSince1970]; NSLog(@"%.f",time10); NSDate *date11 = [NSDate dateWithTimeIntervalSince1970:1493998268]; NSLog(@"%@",date11);

代码示例五:时间转换格式不对等兼容问题

NSString *timeStringA = @"2017-05-05"; NSDateFormatter *formatterA = [[NSDateFormatter alloc] init]; [formatterA setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *dateA = [formatterA dateFromString:timeStringA]; NSString *timeStringB = @"2017-05-05 00:00:00"; NSDateFormatter *formatterB = [[NSDateFormatter alloc] init]; [formatterB setDateFormat:@"yyyy-MM-dd"]; NSDate *dateB = [formatterB dateFromString:timeStringB]; NSLog(@"-----%@",dateA);---> (null) NSLog(@"-----%@",dateB);--->(null) NSDate *dateC = [formatterB dateFromString:[self dateFormatWithoutTimeWithFormatString:@"yyyy-MM-dd" timesString:timeStringB]]; NSLog(@"%@",dateC);2017-05-04 16:00:00 +0000 // 当时间格式和formatter格式不对等的时候会出现null的情况,这个时候你对比时间计算就会出问题 - (NSString *)dateFormatWithoutTimeWithFormatString:(NSString *)formatString timesString:(NSString *)timeStr { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSDateFormatter *dateFormatterNoYearAndSeconds = [[NSDateFormatter alloc] init]; [dateFormatterNoYearAndSeconds setDateFormat:formatString]; [dateFormatterNoYearAndSeconds setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; return [dateFormatterNoYearAndSeconds stringFromDate:[dateFormatter dateFromString:timeStr]]?:timeStr; }

很简单的知识点记录下而已,网上有很多关于NSDate的扩展,很多都包装好了,最近处理时间的时候打印看到了一些问题,就仔细看了下,一般来说都不会有问题,只是更加了解下时间时区之前的切换问题,明白一点就够了,NSDate就是0时区的时间点,如果你不手动设置时区,默认咱们就是东八区,时间转换成NSDate就会小八小时,但是转换成NSString默认又会加上时区差,还有一点,切换时间的时候,从默认时区修改成了其他时区,你小心你的时间戳会有时区上的差异,记得最后比较下你转换前的时区和转换后的时区,默认的时间戳也是0时区为准的

转载请注明原文地址: https://www.6miu.com/read-32491.html

最新回复(0)