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", -3*60*60)

這裏我們同時要知道一個很重要的概念,就是在 *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

如果需要自定義的星期幾名,需要搭配 timeWeekday()函數,返回 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 類型的納秒數

參考資料

本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。

原作者: amc,歡迎轉載,但請註明出處。

原文標題:Go 語言 time 包常用用法筆記

發佈日期:2017-07-03

原文鏈接:https://cloud.tencent.com/developer/article/1456484

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章