博客 / 詳情

返回

Go 語言 time 包常用用法筆記

Go 的時間操作基本上都用 time 包,比 C 的 time 函數和 timeval 等 struct 好用多了。不過 time 包還是有不少用法和其他語言不同的,所以有必要寫個筆記記錄一下。

本文鏈接:https://segmentfault.com/a/1190000020944345,首次發佈於雲+社區

*time.Location 類型
和其他文章不同的是,本文我從時區講起。在 Go 中,表示時區的類型是 type Location struct{...},代碼中使用 *time.Location 對象。

對於不嚴格的場景而言,可以獲取服務器所處的時區。但是本文不建議這個方法。因為一台服務器服務的時區是事先可知的,或者説是需要對接的時區信息也是已知的(比如對接微信,那麼時間肯定是東八區,而不是 UTC 時間)。獲得東八區時區的代碼如下:

loc, _ := time.LoadLocation("Asia/Shanghai")
之後這個 loc 可以作為常量使用。是否能夠拿到時區,取決於機器本地的 zoneinfo 文件。後文也將使用這個 loc 作為全局變量。

也可以自定義一個時區名稱,比如我們人工添加一個巴西利亞時間:

brazil := time.FixedZone("Brazil/Brasilia", -36060)
這裏我們同時要知道一個很重要的概念,就是在 *Location 的加持下,一個 Time 類型本身是同時記錄着 UTC 時間和本地時間的,這就使得一個 Go 時間類型不會因為時區而出現歧義,比如你可以用一個東八區的 Time 和西八區的 Time 隨意進行運算也不會出錯。這一特性使得時間類型變得極為實用。

time.Time 類型
Time 創建及與 string 類型互轉
最基本的創建時間類型的接口:

t := time.Now()
此外,很多資料會跟你説採用 Local() 函數獲得本地時間,但基於前述理由,我建議固定指定 location:

t := time.Now().In(loc)
其他的幾個創建時間的函數:

t := time.Date(y, m, d, h, min, s, nsec, loc):用從年到納秒,以及時區信息,創建一個時間。參數均為整型
t := time.Unix(s, nsec):使用 Unix UTC 時間戳來創建時間
如果將 time 類型轉換成字符串,採用以下函數:

s := t.Format("2006-01-02 15:04:05.000") // 輸出如:"2019-07-03 22:10:23.437"
通過已知格式的字符串解析時間的函數為:

t, err := time.ParseInLocation("2006-01-02 15:04:05", s, loc)
略微瞭解過 Go time 的人都知道,Go 時間格式化採用的並不是傳統的 YYYY-MM-DD hh:mm:ss 格式。這裏有一份對應表,便於組裝字符串時查閲——以時間 1609-08-12 19:02:35 PM +03:00 Aug Wed PDT 為例,這個時間的含義是:1609年9月12日,北美太平洋地區時間下午7:02:35,應用以下格式的輸出舉例:

類型 格式符 輸出舉例 説明
年 2006 1609 ​
​ 06 09 ​
月 01 08 ​
​ 1 8 ​
​ Jan Aug ​
​ January August ​
日 02 02 ​
​ 2 2 ​
周幾 Mon Wed 注意,格式符裏沒有數字化的周幾信息,需要自己拼。參見後文
​ Monday Wednesday ​
小時 03 07 12小時制,01~12,12點表示正午
​ 3 7 12小時制,1~12,12點表示正午
​ 15 19 24小時制,0~23,永遠都是兩位數字,不足2位補0,如早上7點:"07"
分鐘 04 02 ​
​ 4 2 ​
秒 05 35 ​
​ 5 35 ​
上 / 下午 PM PM ​
小數點後秒數 .000 .123 ​
​ .000000 .123456 ​
​ .000000000 .123456789 實際上,可以是小於9位的任意位數的0,只要是以 . 打頭
時區偏移 -0700 +0300 ​
​ -07:00 +03:00 ​
​ Z0700 +0300 ​
​ Z07:00 +03:00 ​
時區名 MST PDT ​
如果需要自定義的星期幾名,需要搭配 time 的 Weekday()函數,返回 Weekday 類型(等同於 int 類型),以 0 代表星期天。如下:

wday := []string{"日", "一", "二", "三", "四", "五", "六"}
s := fmt.Sprintf(t.Format("2006-01-02 15:04:05 星期%s"), wday[t.Weekday()])
fmt.Println(s) // 1609-08-12 19:02:35 星期三
時間比較
time.Time 提供了一個 IsZero() 函數來判斷時間類型是否為空的狀態。空時間所指代的時間是 UTC 時間公元元年 00:00:00,這是 t := time.Time{} 所生成的時間。

主要的比較函數如下:

func (t Time) IsZero() bool
func (t Time) After(u Time) bool:判斷是否在另一個時間之後
func (t Time) Before(u Time) bool:判斷是否在另一個時間之前
func (t Time) Equal(u Time) bool:判斷兩個時間是否相等
func (t Time) Sub(u Time) Duration:計算兩個時間之間的差。Duration 類型會在下一小節説明

注意這個和 Add() 函數的使用場景是完全不同的,不得不吐槽一下兩者的命名……
時間運算
func (t Time) Add(d Duration):加上一個時間段,返回一個新的時間。d 也可以是負的時間
func (t Time) AddDate(年, 月, 日):加上一個日期,獲返回一個新的時間。各參數均為整型,可以是負數

比如 t.AddDate(0, 1, -1) 表示加上一個月之後再減一天
func Since(u Time) Duration:表示當前時間與一個過去的時間的差;如果被比較的時間是將來時間的話,那麼返回負的 Duration

等價於 time.Now().Sub(t)
func Until(u Time) Duration:這是Since` 的反邏輯

等價於 t.Sub(time.Now())
獲取時間的基本函數
以下函數可以獲取時間的基本信息,返回均為整型,很好理解:

t.Year()
t.Month()
t.Day()
t.Weekday():返回以星期天為 0 的星期幾數值
t.YearDay():返回處於每一年的第幾天
t.Hour()
t.Minute()
t.Second()
t.Nanosecond():時間的毫秒部分,int 類型
t.Unix():返回 Unix UTX 時間戳,int64 類型
Duration 類型
Duration 類型的作用是用來表示兩個時間點之間的時間段。Duration 實際上是 int64 類型,單位是納秒。但在實際編碼中,基本上不會直接賦值一個數字,而是用 time 提供的常量,如:

tenSecs := 10 * time.Second
twoHours := 2 * time.Hour
其他常量還有:

const (

    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute

)
此外,Duration 類型還有下面的實用的方法:

func (d Duration) Round(m Duration) Duration:表示按照 m 給定的單位,返回四捨五入
func (d Duration) Truncate(m Duration) Duration:表示按照 m 給定的單位,返回舍尾數計算
func (d Duration) String() string:給出幾小時幾分鐘幾秒的字符串格式,非常適合打日誌
Hours(), Minutes(), Seconds():返回 float64 格式,也就是小數形式的小時 / 分鐘 / 秒數
Nanoseconds():返回 int64 類型的納秒數

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.