淺談 Timestamp === ###### tags: `技術分享` 舉例兩組timestamp,然後以下是相等於個別時區,轉換成人在看的時間格式 1599753600 - 1599839999 ## 台灣時間 UTC+8 2020/09/11 00:00:00 2020/09/11 23:59:59 ## 格林威治時間 UTC 2020/09/10 16:00:00 2020/09/11 15:59:59 ## 美東時間 UTC-4 2020/09/10 12:00:00 2020/09/11 11:59:59   --- ## 1. 問題: 想要查今天的資料,時間範圍限定在今天。 請問把下列時間丟到timestamp 轉換,會得到『1599753600』呢? A. 2020/09/11 00:00:00 B. 2020/09/10 16:00:00 C. 2020/09/10 12:00:00 以上選項都很爛,因為關鍵點,還是這些時間的『**時區**』。 所以沒給時區丟下去轉timestamp,只會有兩種可能: ``` 方案1. 程式處理把你帶來的時間,自動視為是UTC時區的時間。 ``` ``` 方案2. 看目前機器所在的時間,自動視為目前所在的時區時間。 ``` 若是以第2點的方式,就會很可怕,你機器擺在不同的地區,轉出來的timestamp就不同。   --- ## 2. 實作上常發生誤會的原因: 目前我們系統上顯示的是『美東時間』 所以在台灣工作的我們,在2020/09/11 早上09:00am,打開系統一看。 看到的是顯示『美東時間』,2020/09/10 晚上21:00pm 。 資料的查詢條件,是帶入timestamp,那麼我們要把目前抓到的時間,轉成timestamp,請問要怎麼轉? 選項如下: A. 2020/09/11 09:00:00 (查詢一整天就會是 2020/09/11 00:00:00 ~ 2020/09/11 23:59:59) B. 2020/09/10 21:00:00 (查詢一整天就會是 2020/09/10 12:00:00 ~ 2020/09/11 11:59:59) 有沒有強烈的**既視感**,沒錯,就是上面我們講到的狀況     問題不在於帶什麼區間,而是你有沒有辦法,帶給轉換timestamp做轉換的處理函式,告訴他,你給的時間是用什麼**時區**。 所以看到程式有人處理的方式,是事先 加/減 12小時,4小時,8小時...... 的用加減去轉換,那麼程式碼的作者。 可能不清楚丟給程式幫忙轉換timestamp,是用方案一,還是方案二。   不過反過來說,若沒有辦法把『時區』的資訊,帶到轉換函式, 至少你要知道你使用的函式,是看怎麼看到你帶進來時間,把它當作什麼時區。 (我不確定所有的程式語言函式,都可不可以都吃一些像iso之類的有時區的標準格式,或者處理方式就很死板,方案1 or 方案2的轉換方式,沒二話)。     --- ## 3. 那麼,作為資料的寫入方,寫入資料庫的timestamp的時候,要怎麼做呢? 在golang來說就是 ``` go time.Now().Unix() ``` 那要指定時區嗎?不指定時區嗎? 當然不用,無論在什麼樣的時區,當下的時間那一瞬間,timestamp 都是一樣的 ``` 台灣時間UTC+8 2020/09/11 00:00:00 = 格林威治時間 UTC 2020/09/10 16:00:00 = 美東時間 UTC-4 2020/09/10 12:00:00 ```     --- ## 4. golang抓時間的format轉換,與『識別時區』很有關係 ``` go package main import ( "log" "time" ) func main() { log.Println("目前時間", time.Now(), "timestamp:", time.Now().Unix()) // 2020/09/11 20:53:43 目前時間 2020-09-11 20:53:43.048544 +0800 CST m=+0.000089287 timestamp: 1599828823 // 指定抓目前時間是UTC的狀況 // 關鍵在這裡,format幫忙轉換的時區,它要抓哪裡的時區? // 以結果來看,它就是幫你轉成UTC的時區 temp := time.Now().UTC().Add(8 * time.Hour) log.Println(temp.Zone()) // 2020/09/11 20:53:43 UTC 0 log.Println(temp.Format("2006-01-02 15:04:05")) // 2020/09/11 20:53:43 2020-09-11 20:53:43 // 即便format的格式有帶zone,跟它轉出來的時區似乎無關 log.Println(temp.Format("2006-01-02 15:04:05Z0800")) // 2020/09/11 20:53:43 2020-09-11 20:53:43Z0800 log.Println("沒有指定抓目前時間是UTC的狀況") temp2 := time.Now() log.Println(temp2.Zone()) // 2020/09/11 20:53:43 CST 28800 // 這裡的format就幫你抓台灣的時區 // 所以稍微想一下,如果你的機器所在地區,在某個奇怪的時區.......事情就悲劇了 log.Println(temp2.Format("2006-01-02 15:04:05")) // 2020/09/11 20:53:43 2020-09-11 20:53:43 log.Println(temp.Format("2006-01-02 15:04:05Z0800")) // 2020/09/11 20:53:43 2020-09-11 20:53:43Z0800 } ```   --- # 5. 尋找目標的timestamp 如果我們要找指定的時間,然後轉換成timestamp去資料庫挖資料 應該怎麼做呢? 一樣的,把你認知的時間,包含『時區』的資訊,帶給它做轉換 ``` go package main import ( "fmt" "time" ) func main() { // 讓程式自己抓系統目前時區 t := time.Now().Add(-1 * time.Hour).Unix() fmt.Println(t) // 1599826859 // 讓程式指定UTC時間 t2 := time.Now().Add(-1 * time.Hour).UTC().Unix() fmt.Println(t2) // 1599826859 // 再次證明一下,不管是什麼時間,轉換出來的timestamp是一樣 // 指定台灣時間 // 輸入的時間:2020-09-11 20:00:00 // 轉換結果:1599825600 // 我們看一下轉換有沒有符合預期 t3, err := time.Parse("2006/01/02 15:04:05 MST", "2020/09/11 20:00:00 CST") if err != nil { fmt.Println(err) } fmt.Println(t3) // 2020-09-11 20:00:00 +0800 CST fmt.Println(t3.Unix()) // 1599825600 符合預期! // 指定時區也是一種方式 loc, locErr := time.LoadLocation("Asia/Taipei") if locErr != nil { } // recentTime := time.Unix(ret[0].Begin.Unix(), 0).In(loc).Format("2006-01-02 15:04:05") + " (" + loc.String() + ")" now := time.Now().In(loc).Format("2006-01-02 15:04:05") + " (" + loc.String() + ")" log.Println(now) } ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.