總結(jié) - Unix 紀(jì)元不止是個(gè)日期

toilet

前幾日調(diào)整服務(wù)器緩存功能代碼時(shí)為方便處理時(shí)間戳,存儲(chǔ)時(shí)將日期時(shí)間轉(zhuǎn)為秒數(shù)的整數(shù)格式,使用的編程語(yǔ)言是 Ruby 當(dāng)時(shí)并不知曉這種存儲(chǔ)方式是 Unix 世界早已通用的時(shí)間格式。

事后數(shù)據(jù)運(yùn)維同事查看緩存說(shuō)明文檔時(shí),反問(wèn)時(shí)間戳的整數(shù)格式是否從格林尼治時(shí)間算起?鬼知道 Time.now.to_i 是怎么算的,走心的疑惑還有其他計(jì)算方式嗎?無(wú)知的反問(wèn)語(yǔ)里竟透露著焉敢質(zhì)疑的咄咄逼人,久久不知如何解釋。

Time#to_i

Returns the value of time as an integer number of seconds since the Epoch.

API 解釋為從 Epoch 算起的總秒數(shù),看著陌生的 Epoch 誤以為是個(gè)專有名稱,但英文再差還是有份自信它怎么也不會(huì)音譯為格林尼治。

Epoch 時(shí)期; 紀(jì)元; 世; 新時(shí)代;

Epoch Time 指一個(gè)特定的時(shí)間:1970-01-01 00:00:00 UTC。

UTC 又是什么?

協(xié)調(diào)世界時(shí)(英:Coordinated Universal Time ,法:Temps Universel Coordonné),又稱世界統(tǒng)一時(shí)間,世界標(biāo)準(zhǔn)時(shí)間,國(guó)際協(xié)調(diào)時(shí)間。英文(CUT)和法文(TUC)的縮寫不同,作為妥協(xié),簡(jiǎn)稱UTC。

UTC 時(shí)間是以原子時(shí)秒長(zhǎng)為基礎(chǔ),在時(shí)刻上盡量接近于世界時(shí)的一種時(shí)間計(jì)量系統(tǒng),是新的標(biāo)準(zhǔn)時(shí)間。

新的標(biāo)準(zhǔn)時(shí)間?那舊標(biāo)準(zhǔn)時(shí)間的有那些?原來(lái)就是格林尼治時(shí)間。

格林尼治標(biāo)準(zhǔn)時(shí)間(Greenwich Mean Time,GMT)是指位于英國(guó)倫敦郊區(qū)的皇家格林尼治天文臺(tái)的標(biāo)準(zhǔn)時(shí)間,本初子午線被定義為通過(guò)那里的經(jīng)線。

由于地球每天的自轉(zhuǎn)有些不規(guī)則,而且正在緩慢減速,因此,格林尼治時(shí)間已不再被作為標(biāo)準(zhǔn)時(shí)間使用。新的標(biāo)準(zhǔn)時(shí)間,是由原子鐘報(bào)時(shí)的協(xié)調(diào)世界時(shí)(UTC)。

明白了 GMT/UTC 的標(biāo)準(zhǔn)時(shí)間方案更替的承接關(guān)系,那 1970 年發(fā)生了什么,以至于 Unix 系統(tǒng)以它作 “紀(jì)元”。

原來(lái) Unix 就是在那個(gè)時(shí)代產(chǎn)生的,1969 年發(fā)布的雛形,最早是基于硬件 60Hz 的時(shí)間計(jì)數(shù)。

1971年底出版的《Unix Programmer's Manual》里定義的 Unix Time 是以 1971年1月1日00:00:00 作為起始時(shí)間,每秒增長(zhǎng) 60。考慮到 32 位整數(shù)的范圍,如果每秒 60 個(gè)數(shù)字,則兩年半就會(huì)循環(huán)一輪,于是改成以秒為計(jì)數(shù)單位。循環(huán)周期有136年之長(zhǎng),就不在乎起始時(shí)間是 1970 還是 1971 年,遂改成人工記憶、計(jì)算比較方便的1970年。

看起來(lái)很亂的概念此時(shí)清晰很多,Unix 的世界開啟了 “紀(jì)元”,Unix 時(shí)間戳也就成為了一個(gè)專有名稱。

Unix 時(shí)間戳是一種時(shí)間表示方式,定義為從格林尼治時(shí)間 1970年01月01日 00時(shí)00分00秒 起至現(xiàn)在的總秒數(shù),不考慮閏秒。

Unix 時(shí)間戳的英文稱呼列表:

  • POSIX time
  • Epoch time
  • Unix epoch
  • Unix time
  • Unix timestamp

GMT/UTC 是兩套時(shí)間標(biāo)準(zhǔn);1970 年是 Unix 系統(tǒng)誕生的年代里易于人工記憶的年份;1970 年作為 Unix 系統(tǒng)歷史長(zhǎng)河中里程碑式的一年,正式開啟了 Unix 世界的 “紀(jì)元”,番邦稱 Epoch。

UTC 本質(zhì)強(qiáng)調(diào)的是比 GMT 更為精確的世界時(shí)間標(biāo)準(zhǔn),不過(guò)對(duì)于開發(fā)者而言,GMT 與 UTC 的功能與精確度是沒有差別的。

HTTP 響應(yīng)頭中的日期就是使用舊款的 GMT 標(biāo)準(zhǔn)時(shí)間:

curl -I jianshu.com
HTTP/1.1 301 Moved Permanently
Server: Tengine
Date: Mon, 12 Dec 2016 14:29:05 GMT
Content-Type: text/html
Content-Length: 278
Connection: keep-alive
Location: http://www.lxweimin.com/

MySQL

MySQL 不止是穩(wěn)定好用存儲(chǔ)數(shù)據(jù)的庫(kù),更是一套超強(qiáng)的工具集,生成與反解 Unix 時(shí)間戳的操作也只是一條命令的執(zhí)行。

mysql> select unix_timestamp();
+------------------+
| unix_timestamp() |
+------------------+
|       1481545686 |
+------------------+
1 row in set (0.01 sec)

mysql> select from_unixtime(1481545686);
+---------------------------+
| from_unixtime(1481545686) |
+---------------------------+
| 2016-12-12 20:28:06       |
+---------------------------+
1 row in set (0.01 sec)

感興趣的可以查詢一下這兩個(gè)函數(shù),用法相當(dāng)靈活,以便需要時(shí)腦中多一套解決思路,莫要有事沒事就寫腳本。

生長(zhǎng)在天朝,配置數(shù)據(jù)庫(kù)時(shí)除了中文編碼外就是時(shí)間的設(shè)置,那么如何查看當(dāng)前數(shù)據(jù)庫(kù)是否按配置的時(shí)區(qū)在運(yùn)行呢?

$ cat /ect/my.cnf
[mysqld]
default_time_zone='+08:00'
mysql> select timediff(now(), utc_timestamp) as date_area;
+-----------+
| date_area |
+-----------+
| 08:00:00  |
+-----------+
1 row in set (0.00 sec)

mysql> select utc_timestamp();
+---------------------+
| utc_timestamp()     |
+---------------------+
| 2016-12-12 13:51:15 |
+---------------------+
1 row in set (0.00 sec)

mysql> select current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2016-12-12 21:50:38 |
+---------------------+
1 row in set (0.00 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2016-12-12 21:50:49 |
+---------------------+
1 row in set (0.00 sec)

MySQL# UTC_TIMESTAMP

Returns the current UTC date and time as a value in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS format, depending on whether the function is used in a string or numeric context.

UTC 標(biāo)準(zhǔn)時(shí)間按指定的格式顯示,那么還有其他的顯示格式?查詢 API 果然無(wú)規(guī)矩不成方圓,發(fā)現(xiàn)真有個(gè)函數(shù)可以獲取不同標(biāo)準(zhǔn)時(shí)間的顯示格式,自己過(guò)于膚淺,這才意示到優(yōu)秀的工具中隨便顯示的時(shí)間格式都是各有出處。

mysql> select get_format(datetime,'iso') as iso;
+-------------------+
| iso               |
+-------------------+
| %Y-%m-%d %H:%i:%s |
+-------------------+
1 row in set (0.01 sec)

顯示格式的標(biāo)準(zhǔn)不多,貼一下權(quán)當(dāng)備忘:

Function Call Result
GET_FORMAT(DATE,'USA') '%m.%d.%Y'
GET_FORMAT(DATE,'JIS') '%Y-%m-%d'
GET_FORMAT(DATE,'ISO') '%Y-%m-%d'
GET_FORMAT(DATE,'EUR') '%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL') '%Y%m%d'
GET_FORMAT(DATETIME,'USA') '%Y-%m-%d %H.%i.%s'
GET_FORMAT(DATETIME,'JIS') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'ISO') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'EUR') '%Y-%m-%d %H.%i.%s'
GET_FORMAT(DATETIME,'INTERNAL') '%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA') '%h:%i:%s %p'
GET_FORMAT(TIME,'JIS') '%H:%i:%s'
GET_FORMAT(TIME,'ISO') '%H:%i:%s'
GET_FORMAT(TIME,'EUR') '%H.%i.%s'
GET_FORMAT(TIME,'INTERNAL') '%H%i%s'

Terminal

若在數(shù)據(jù)庫(kù)中操作,使用上述函數(shù)已經(jīng)可以隨手生成、解析 Unix 時(shí)間戳,若未在數(shù)據(jù)庫(kù)中操作,難不成為查看 Unix 時(shí)間戳還要再登錄數(shù)據(jù)庫(kù)?打開命令終端,也是一個(gè)命令分秒間釋然的事情。

$ uname -s
Darwin
$ date +%s
1481546766
$ date -r 1481546766
2016年12月12日 星期一 20時(shí)46分06秒 CST

$ cat /etc/redhat-release
CentOS release 6.5 (Final)
$ date +%s
1481546890
$ date -d @1481546890
2016年 12月 12日 星期一 20:48:10 CST

$ irb
irb(main):001:0> t = Time.now.to_i
=> 1481547158
irb(main):002:0> Time.at(t)
=> 2016-12-12 20:52:38 +0800

> window.userAgent
< "mozilla/5.0 (macintosh; intel mac os x 10_10_5) applewebkit/601.7.7 (khtml, like gecko) version/9.1.2 safari/601.7.7"
> var t = Math.round(new Date().getTime() / 1000)
< undefined
> t
< 1481601053
> new Date(t * 1000)
< Tue Dec 13 2016 11:50:53 GMT+0800 (CST) 

CST 又是什么時(shí)間標(biāo)準(zhǔn)?CST 可視為美國(guó)、澳大利亞、古巴或中國(guó)的標(biāo)準(zhǔn)時(shí)間,可為如下 4 個(gè)不同時(shí)區(qū)的縮寫:

  • 古巴標(biāo)準(zhǔn)時(shí)間:Cuba Standard Time UT-4:00
  • 中國(guó)標(biāo)準(zhǔn)時(shí)間:China Standard Time UT+8:00
  • 美國(guó)中部時(shí)間:Central Standard Time (USA) UT-6:00
  • 澳大利亞中部時(shí)間:Central Standard Time (Australia) UT+9:30

簡(jiǎn)單查找資料未找到 CST 存在的意義,僅僅是上述幾行文字的解釋。TODO: CST 產(chǎn)生的原因

參考列表中 百科:Unix時(shí)間戳 值得簡(jiǎn)單閱讀,內(nèi)有彩蛋。

其他標(biāo)準(zhǔn)時(shí)間

CET(Central European Time,CET)歐洲中部時(shí)間是比世界標(biāo)準(zhǔn)時(shí)間(UTC)早一個(gè)小時(shí)的時(shí)區(qū)名稱之一。

它被大部分歐洲國(guó)家和部分北非國(guó)家采用。

冬季時(shí)間為 UTC + 1,夏季歐洲夏令時(shí)為 UTC + 2。

DST (Daylight Saving Time)夏日節(jié)約時(shí)間,指在夏天太陽(yáng)升起的比較早時(shí),將時(shí)鐘撥快一小時(shí),以提早日光的使用,在英國(guó)則稱為夏令時(shí)間(Summer Time)。

這個(gè)構(gòu)想于 1784年由美國(guó)班杰明·富蘭克林提出來(lái),1915 年德國(guó)成為第一個(gè)正式實(shí)施夏令日光節(jié)約時(shí)間的國(guó)家,以削減燈光照明和耗電開支。自此以后,全球以歐洲和北美為主的約 70 個(gè)國(guó)家都引用了這個(gè)套方案。

歐洲手機(jī)上也有很多 GSM 系統(tǒng)的基地臺(tái),除了會(huì)傳送當(dāng)?shù)貢r(shí)間外也包括夏令日光節(jié)約時(shí)間,做為手機(jī)的時(shí)間標(biāo)準(zhǔn),使用者可以自行決定開啟或關(guān)閉。

值得注意的是,某些國(guó)家有實(shí)施「夏日節(jié)約時(shí)間」的制度,出國(guó)時(shí)別忘了跟隨當(dāng)?shù)亓?xí)慣在表上調(diào)整一下,這可是機(jī)械表沒有的功能設(shè)計(jì)!

各標(biāo)準(zhǔn)時(shí)間的計(jì)算

  • UTC = GMT
  • CET = UTC/GMT + 1
  • CST = UTC/GMT + 8
  • CST = CET + 9

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容