------------------------------------------
涉及到時間處理時,Parse 和 Format 是最為常見的處理了。
Parse:將字符串格式的時間轉為 time.Time,類似 PHP 中的 strtotime;Format:將 time.Time 格式化為字符串格式的時間,類似 PHP 中的 timetostr。
提到時間,它一定需要跟時區一起才有意義,比如 15:30:00 這個時間,其實並不明確,因為你不知道這是北京時間還是東京時間。而一般人的理解里,如果沒提到時區,就默認是當地的時區,比如我說 15:30:00,大家都能理解為下午三點,是因為同在北京時區里。
回到 time.Format,它返回的是固定的字符串,格式化時它是需要明確時區信息的,但 Format 函數卻沒有時區參數。事實上它的時區信息來源於 time.Time 結構體的 loc 字段,而並不允許作為參數傳入。這也解釋了為什么 time.Now().Format() 會返回當地時區的時間字符串,因為 time.Now() 返回的 time.Time 默認是當地時區。
type Time struct {
sec int64
nsec int32
loc *Location
}
總結起來就是:time.Format 的時區信息來源於 Time 結構體中的 loc,time.Now().Format() 返回的是當地時區的時間。
然后是 time.Parse,如果它的參數沒有帶入時區信息,比如沒有 +0800 這樣的信息,它將默認使用 UTC 時間,這意味着:
s := time.Now().Format("2006-01-02 15:04:05")
t, _ := time.Parse("2006-01-02 15:04:05", s)
上面的 s 和 t 已經完全不一樣了,因為 s 返回的是當地時區,而 t 則變成了 UTC 時間。這也解釋了為什么經過這么一個習慣性操作,得到的時間居然是不符合預期的了。
正確的做法是使用 ParseInLocation 來 Parse 明確是同一時間的不帶時間信息的時間字符串:
s := time.Now().Format("2006-01-02 15:04:05")
t, _ := time.ParseInLocation("2006-01-02 15:04:05", s, time.Local)
這樣做才會符合習慣於 strtotime 和 timetostr 的結果預期。
總結起來就是:如果時間字符串中帶了時區信息才去使用 time.Parse,否則使用 time.ParseInLocation。