這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
一段代碼
這裡有一段代碼 play 更能解說 layout. 可以看出, go 自動識別並轉換 time 字串是完全可能的.
time package
go 的time package 提供了time.Format函數,用來對時間進行格式化輸出。
類似的還有time.Parse用來解析字串類型的時間到time.Time。這是兩個互逆的函數。
問題是,go 採用的格式化 layout 和我們以往所用的任何經驗都不同。以至於初次接觸總是一頭霧
水。
其實 go 提供的這個 layout 對演算法的實現非常科學高效,而且很規律。下面我們詳細分解下。
直接上個對應表
前面是含義,後面是 go 的表示值,多種表示,逗號”,“分割
- 月份 1,01,Jan,January
- 日 2,02,_2
- 時 3,03,15,PM,pm,AM,am
- 分 4,04
- 秒 5,05
- 年 06,2006
- 周幾 Mon,Monday
- 時區時差表示 -07,-0700,Z0700,Z07:00,-07:00,MST
- 時區字母縮寫 MST
您看出規律了麼!哦是的,你發現了,這裡面沒有一個是重複的,所有的值表示都唯一對應一個時間部分。並且涵蓋了很多格式組合。
比如小時的表示(原定義是下午3時,也就是15時)
- 3 用12小時製表示,去掉前置0
- 03 用12小時製表示,保留前置0
- 15 用24小時製表示,保留前置0
- 03pm 用24小時制am/pm表示上下午表示,保留前置0
- 3pm 用24小時制am/pm表示上下午表示,去掉前置0
補充
2014-02-26日 在解析時 layout 中要用 pm 或 PM, 分別對應資料中的 am/pm, AM/PM, 大小寫敏感. 如果 layout 有前置 0 ,那資料中就不能省略
又比如月份
- 1 數字表示月份,去掉前置0
- 01 數字表示月份,保留前置0
- Jan 縮寫單詞表示月份
- January 全單詞表示月份
執行個體對應
真即時間:我的UTC時間是 2013年12月5日,我的本地時區是Asia/Shanghai
字元表示: 2013 12 5 CST
Go Layout: 2006 01 2 MST
真即時間:我的UTC時間是 2013年12月22點,我的本地時區是Asia/Shanghai
字元表示: 2013 12 22 CST
Go Layout: 2006 01 15 MST
而所有這些數位順序正好是1,2,4,5,6,7和一個時區
補充
2014-01-17日 發現上面的時間舉例不準確,應該加上時分秒才能說明清楚時區的問題
下面樣本時區問題
真即時間:我的本地時間是 2014-01-17 01:19:15,我的本地時區是 Asia/Shanghai
RFC3339格式:2006-01-02T15:04:05Z07:00
RFC3339輸出:2014-01-17T01:19:15+08:00
自訂格式:2006-01-02 15:04:05 -07:00
自訂輸出:2014-01-17 01:19:15 +08:00
自訂格式:2006-01-02 15:04:05 -07:00 MST
自訂輸出:2014-01-17 01:19:15 +08:00 CST
UCT()輸出:2014-01-16 17:19:15.9092754 +0000 UTC
注意看:UTC時間和本地時間和時區時差的差異
也就是說:
未經UTC()函數處理的時間輸出表示的是本地時間帶時區(如果是帶時區的格式)
如果要計算 UTC 時間一定要記得使用UTC()函數後再進行其他動作.
MST是北美山區時區的英文縮寫, Asia/Shanghai對應的時區縮寫是CST.這個CST是從所在作業系統擷取的,windows系統和別的不同,還做了特殊處理,具體比較複雜.感興趣請自己分析zoneinfo_abbrs_windows.go.
注意縮寫雖然是代表某個時區,但是由於縮寫有重複的,所以無法計算時差 參見 時區縮寫
靠縮寫來判斷時差是不可靠的
除了上面的時區縮寫名稱表示時區, 時區還可以用
Z0700,Z070000,Z07:00,Z07:00:00
-0700,-070000,-07:00,-07:00:00
首碼 “Z"和”-” 兩種風格以時差表示時區.
其實還有一個秒的 repeated digits for fractional seconds 標記法
用的是 0和9 ,很少用,原始碼裡面是這樣寫的
stdFracSecond0 // ".0", ".00", ... , trailing zeros includedstdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
time.Parse 無時差時區layout
看代碼和輸出
time.Parse("2006-01-02 15:04:05", "2014-01-17 03:06:54")// 2014-01-17 03:06:54 +0000 UTC <nil>
如果layout未定義時差時區,那麼時區是按UTC計算的. 縮寫時區是不可靠的.
那些分界符
除了那些值之外的都是分界符號,自然匹配了,直接舉例子吧
字元表示: 2013-12 21 CST
Go Layout: 2006-01 15 MST
字元表示: 2013年12月21時 時區CST
Go Layout: 2006年01月15時 時區MST
好了,您是否感覺這個表示方法相容度更好,適應性更強呢,更容易記憶呢。
公元前的時間問題
公元前的時間年份是負值,time package輸出沒有問題,但是parser是不支援年份的負值的,不知道這算不算BUG.看官請自己注意.
提交了個 issues. 官方認為問題不嚴重, 這是一種特殊情境, 開發人員可以特別處理下. 無需為此更改time package.
UTC時間 1月2日下午3時4分5秒 2006 年,本地時區-0700 , 還有999999999納秒的零頭