iOS 日期转换解析(一)
时间概念区分
格林威治标准时间GMT
是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能和实际的太阳时相差16分钟。
世界协调时间UTC
UTC是国际无线电咨询委员会制定和推荐的,UTC相当于本初子午线(即经度0度)上的平均太阳时。
它是经过平均太阳时(以格林威治标准时间GMT)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。
其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。
所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准.它其实是个更精确的GMT。
我们一般认为GMT和UTC是一样的,都与英国伦敦的本地时相同。
本地时间
整个地球分为二十四时区,每个时区都有自己的本地时间。
本地时间 = UTC + 时区差。
时区差东为正,西为负。北京时区是东八区,领先UTC八个小时。
其他时间
ISO:标准时间
CST:北京时间(中国标准时间)
时间戳
计算机中看到的UTC时间都是从(1970年01月01日 0:00:00)开始计算秒数,所看到的UTC时间就是从1970年零点到具体时间共有多少秒,这个秒数就是Unix时间戳。
iOS 系统时间相关类
NSDate
当前日期。
图1.png结论:
1.NSDate中存储的为UTC时间。
2.伦敦时区时间。
注意:该方法获取的为设备时间,可通过设置->通用->日期与时间
修改获取的时间值。
NSDateFormatter
日期转换为字符串展示时时间格式。
NSDate *date = [NSDate date];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSString *dateString = [format stringFromDate:date];
NSLog(@"date=%@ \n timeZone= %@ \n dateString= %@",date,format.timeZone,dateString);
NSString *dateStr = @"2020-01-22 18:05:27";
NSDate *dateS = [format dateFromString:dateStr];
NSLog(@"dateS=%@",dateS);
iOS11及以上系统
图2.png
date=Wed Jan 22 18:15:11 2020
timeZone= Asia/Shanghai (GMT+8) offset 28800
dateString= 2020-01-22 18:15:11
dateS=Wed Jan 22 18:05:27 2020
iOS10及以下系统
图3.png
date=2020-01-22 10:18:43 +0000
timeZone= GMT (GMT) offset 0
dateString= 2020-01-22 10:18:43
dateS=2020-01-22 18:05:27 +0000
结论:
1.iOS10及以下系统默认时区为伦敦时区(GMT (GMT) offset 0),iOS11及以上系统默认为本地时区,此处表示为东八区(Asia/Shanghai (GMT+8) offset 28800)。
2.NSDate中存储的为UTC时间,伦敦时区。
3.NSLog输出日志为NSDate通过NSDateFormatter默认时区转换后日期信息。
NSTimeZone
设置时区。
NSDate *date = [NSDate date];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
[format setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]];
NSString *dateString = [format stringFromDate:date];
NSLog(@"date=%@ \n timeZone= %@ \n dateString= %@",date,format.timeZone,dateString);
NSString *dateStr = @"2020-01-22 18:05:27";
NSDate *dateS = [format dateFromString:dateStr];
NSLog(@"dateS=%@",dateS);
iOS11及以上系统
图4.png
date=Wed Jan 22 18:21:35 2020
timeZone= Asia/Shanghai (GMT+8) offset 28800
dateString= 2020-01-22 18:21:35
dateS=Wed Jan 22 18:05:27 2020
iOS10及以下系统
图5.png
date=2020-01-22 10:22:46 +0000
timeZone= Asia/Shanghai (GMT+8) offset 28800
dateString= 2020-01-22 18:22:46
dateS=2020-01-22 10:05:27 +0000
结论:
1.NSDate转时间字符串时,设置时区后系统会将NSDate中的时间转换成设定时区时间字符串。
2.时间字符串转NSDate时,设置时区后系统将时间字符串理解为设定时区时间,按照设定时区时间转换为NSDate内时间。
3.NSLog输出日志为NSDate通过NSDateFormatter默认时区转换后日期信息,与上下文中NSDateFormatter设置无关联。
时间格式字符
(/)
日期分隔符。在某些区域设置中,可以使用其他字符表示日期分隔符。日期分隔符在格式化日期值时分隔日、月和年。格式化输出中用作日期分隔符的实际字符由您的应用程序的当前区域性确定。
(%)
用于表明不论尾随什么字母,随后字符都应该以单字母格式读取。也用于表明单字母格式应以用户定义格式读取。有关更多详细信息,请参见下面的内容。
d
将日显示为不带前导零的数字(如 1)。如果这是用户定义的数字格式中的唯一字符,请使用 %d。
dd
将日显示为带前导零的数字(如 01)。
EEE
将日显示为缩写形式(例如 Sun)。
EEEE
将日显示为全名(例如 Sunday)。
M
将月份显示为不带前导零的数字(如一月表示为 1)。如果这是用户定义的数字格式中的唯一字符,请使用 %M。
MM
将月份显示为带前导零的数字(例如 01/12/01)。
MMM
将月份显示为缩写形式(例如 Jan)。
MMMM
将月份显示为完整月份名(例如 January)。
gg
显示时代/纪元字符串(例如 A.D.)
h
使用 12 小时制将小时显示为不带前导零的数字(例如 1:15:15 PM)。如果这是用户定义的数字格式中的唯一字符,请使用 %h。
hh
使用 12 小时制将小时显示为带前导零的数字(例如 01:15:15 PM)。
H
使用 24 小时制将小时显示为不带前导零的数字(例如 1:15:15)。如果这是用户定义的数字格式中的唯一字符,请使用 %H。
HH
使用 24 小时制将小时显示为带前导零的数字(例如 01:15:15)。
m
将分钟显示为不带前导零的数字(例如 12:1:15)。如果这是用户定义的数字格式中的唯一字符,请使用 %m。
mm
将分钟显示为带前导零的数字(例如 12:01:15)。
s
将秒显示为不带前导零的数字(例如 12:15:5)。如果这是用户定义的数字格式中的唯一字符,请使用 %s。
ss
将秒显示为带前导零的数字(例如 12:15:05)。
f
显示秒的小数部分。例如,ff 将精确显示到百分之一秒,而 ffff 将精确显示到万分之一秒。用户定义格式中最多可使用七个 f 符号。如果这是用户定义的数字格式中的唯一字符,请使用 %f。
t
使用 12 小时制,并对中午之前的任一小时显示大写的 A,对中午到 11:59 P.M 之间的任一小时显示大写的 P。如果这是用户定义的数字格式中的唯一字符,请使用 %t。
tt
对于使用 12 小时制的区域设置,对中午之前任一小时显示大写的 AM,对中午到 11:59 P.M 之间的任一小时显示大写的 PM。
对于使用 24 小时制的区域设置,不显示任何字符。
y
将年份 (0-9) 显示为不带前导零的数字。如果这是用户定义的数字格式中的唯一字符,请使用 %y。
yy
以带前导零的两位数字格式显示年份(如果适用)。
yyy
以四位数字格式显示年份。
yyyy
以四位数字格式显示年份。
z
显示不带前导零的时区偏移量(如 -8)。如果这是用户定义的数字格式中的唯一字符,请使用 %z。
zz
显示带前导零的时区偏移量(例如 -08)
zzz
显示完整的时区偏移量(例如 -08:00)