每个程序员都用过 DateTime
,但真正当前后台进行交互时,才发现这里的复杂性。比如有这么一些关键词:
- GMT
- UT/UTC
- CST
- RFC 1123
- ISO 8601
- Unix Timestamp
还有在常见系统中对应的:
- TimeZone
- Local
🥇 日期/时间及时区
🥈 先从 GMT 说起吧
(Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林威治天文台的标准时间。
通俗的说,就是将地球按经度分成 24 个区,每个区有自己当下时间,比如中国就在东 8 区,代号 +8
。向东走一个区(日本,东九区),手表就要调快一个小时。
🥈 UTC
Coordinated Universal Time,简称 UTC(世界标准时间或世界协调时间)
很多时间被称作 UTC,但 RFC 中均使用 UT 来对比 GMT。
GMT 并不精准,于是以 GMT 为准加上修正而成的时间,被称作为 UT,一般对于我们来说,这两个值没有差别。另外,早年的 PC 好像都是 GMT,后来就换成了 UT 时间。
🥈 CST
China Standard Time (中国标准时间),也就是我们每天所说的北京时间,我国是属东八区,转成 UTC,加上 +8
的时区表示即可。
🥇 日期 / 时间及格式
最后来看下关健性的一个,有了时间,但是在不同国家,不同人群,不同设备之间交流时,用什么样的格式呢。
🥈 RFC 2822
互联网协议 RFC 1123 的子集: RFC 2822
Internet Message Format(前身 RFC 822
)制定最新的日期/时间格式。
1 | Thu, 07 Jul 2016 02:40:59 GMT |
🥈 ISO 8601
其代表着日期和时间的表示方法,全名为《数据存储和交换形式·信息交换·日期和时间的表示方法》。
RFC 1123
中的日期/时间定义实在是太糟糕了。它很难阅读,又很难解析,以英语为背景,并且使用的是 GMT 而非 UTC。
在 RFC 822 发布后,ISO 8601 便成为了事实协议标准,它更容易理解和使用。
目前最新为第三版 ISO8601:2004
如果有可能,请在任何地方使用这种标准。
🔅 日期表示法
年为 4 位数,月、日为 2 位数,例如 2004 年 5 月 3 日可写成
1 | 2004-05-03 |
🔅 时间表示法
小时、分和秒都用 2 位数表示。在 UTC 标准时区(+0
)最后加一个大写字母 Z
,而其他时区用实际时间加时差表示。
下午 2点 30分 50秒
表示为
1 | # UTC 标准时区 |
🔅 日期时间表示法
时间和日期一起表示时,中间用 T
分隔。
比如下面的几个表示法:
** > UTC 标准时区(+0)**
1 | 2016-05-20T08:01:01+00:00 |
** > 北京时区表示法 **
1 | 2016-05-20T16:01:01+08:00 |
** > 精确表示法 **
1 | 2016-05-20T16:01:01.000+08:00 |
其中的 .000
是秒后面的小数点,找到这个解释不容易,感谢 #SO - What does the “.000Z” mean?
🥈 Unix Timestamp
也被称作 时间戳
,它是 GMT 1970年 01月 01日 00时 00分 00秒
起至现在的总秒数。看起来是这样子的:1401200885364
时间戳 0
按照 ISO 8601
格式写出来为 1970-01-01T00:00:00Z
。
另外,Timestamp 是现在时间相对于标准
0时
之间的秒数,是没有时区的概念的。
这种格式在使用起来比较简单,如果不表示 1970 年之前的时间的话,但可读性却也是最差的,所以在 API 中很少有看到这种表示法。(开发者也是 API 的最大用户,可读性很重要。)
🥈 其它表示法
RFC 850
obsoleted by RFC 1036
1 | Sunday, 06-Nov-94 08:49:37 GMT |
ANSI C’s asctime() format
1 | Sun Nov 6 08:49:37 1994 |
🥇 系统时间及时区
那系统又是如何定义当地时间呢?以 iOS 为例:
在 iPhone 中有 2 样东西关系到国际化,当然也关系到时间表示。其中就是 Local 和 TimeZone。
- Local 中可以设置系统的国家,语言、系统默认语言,日期的一些属性,如定义常用格式,如 Short/Medium/Long/Full 等等。
- TimeZone 是指当前时区,可以手动设置,也可以让系统自己网络获取。
🥈 NSTimeZone
通过 Default 取系统时区,可以看到当前为 Shanghai +8
1 | [NSTimeZone defaultTimeZone] |
🥈 NSLocale
NSLocale 中配置着用户的本地化信息,如货币,语言,时间表示
🥇 各语言中的一些表示法
🥈 HTTP Date
https://tools.ietf.org/html/rfc2616#section-3.3
Parses date as an HTTP-date defined by RFC 2616 and converts it to a Time object.
Returns a string which represents the time as RFC 1123 date of HTTP-date defined by RFC 2616:
day-of-week, DD month-name CCYY hh:mm:ss GMT
Note that the result is always UTC (GMT).
1 | Thu, 07 Jul 2016 02:36:59 GMT |
🥈 JavaScript
ECMA 5 更新为 ISO8601,老的版本用的还是 GMT 的表示法,
1 | let n = new Date(); |
Node v6
1 | let n = new Date(); |
🥈 Ruby
Ruby 也是在某一个版本后将日期时间标准升级为 ISO8601 的,具体哪个版本无法查证。
1 | require "date" |
如果我想把 +8 转成 Z 呢?
🥈 Obj-C
iOS 中 Debug 时显示的时间是用 CTS 表示的,Watch 中可以看到
2014-05-25 10:29:04 CST
打印出来又是这样子的,被转成了UTC +0
时区标准时间2014-05-25 02:29:04 +0000
然后在具体使用时,再加上当前的时区,转换成当地时间进行显示,iOS 中可以这样转换:
1 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; |