golang 中 time 包使用教程之基礎使用篇

yudotyang發表於2021-01-10

本文首發於微信公眾號 "Go 學堂",敬請關注

在編寫程式中,我們經常會遇到時間戳和日期字串相互轉換、獲取當前時間、時間之間的比較操作。本文主要介紹 golang 中關於時間常用的操作。

golang 中的時間操作在 time 包中。時間操作的基礎是基於一個 Time 的結構體。時間相關的操作都需要先轉換成 Time 結構體,再通過 Time 結構體相關的函式轉換成目標值。如下圖:

再來看 Time 結構體在原始檔中的定義:

type Time struct {
  wall uint64
  ext int64
  loc *Location
}

01 獲取時間相關操作

1、獲取當前時間戳

函式原型:func (t Time) Unix() int64

示例程式碼:

seconds := time.Now().Unix()

2、獲取當前年月日時分秒和星期幾(數字不帶前導 0)

函式原型:

func (t Time) Date() (yearint, month Month, dayint)

func(t Time) Clock() (hour, min, secint)

func(t Time) Hour() int

func(t Time) Minute() int

func(t Time) Second() int

示例程式碼:

//獲取當前時間的Time結構體例項
t := time.Now()

//通過Date函式同時獲取年月日
year, month, day := t.Date()
//假設日期為2021-1-7 列印結果為 year:2021, month:1, day:7
fmt.Printf("year:%d, month:%d, day:%d\n", year, month, day)

//通過Clock函式同時獲取時分秒
hour, minute, second := t.Clock()
//假設時間是18:51:9 列印結果 hour:18,minute:51,second:9
fmt.Printf("hour:%d,minute:%d,second:%d\n", hour, minute, second)

//也可以單獨獲取年、月、日、時、分、秒、星期幾
year := t.Year() //獲取所屬年份
month := t.Month() //獲取所屬月份,不帶前導零
day := t.Day() //獲取所屬日,不帶前導零
hour := t.Hour() //獲取當前小時
minutes := t.Minute() //獲取當前分鐘
seconds := t.Seconds() //獲取當前描述
nanosecond := t.Nanosecond() //獲取當前納秒數

3、獲取今天是星期幾

函式原型:func (t Time) Weekday() Weekday

該函式返回值型別是 Weekday,即可以表示成數字星期幾,也可以輸出成星期的英文表示。

示例程式碼:

//獲取當前時間的Time結構體例項
t := time.Now()
//獲取是星期幾, t.Weekday返回的是Weekday型別
//Weekday型別在原始碼的定義是 type Weekday int
weekday := t.Weekday()
// 列印出星期幾的數字表示和英文表示
// 假設是星期四,列印結果:weekday=4, weekday(string)=Thursday
fmt.Printf("weekday=%d, weekday(string)=%s\n\n", weekday, weekday)

4、返回當前時間是一年中的第幾天

函式原型:func (t Time) YearDay() int

示例程式碼:

//獲取當前時間的Time結構體例項
t := time.Now()

yearday := time.Now().YearDay()
// 假設時間是2021-01-07日 列印結果 yearday = 7
fmt.Printf("yearday=%d\n\n", yearday)

02 時間戳和日期字串之間的轉換

1、時間戳格式化成日期字串

函式原型:

func Unix(sec int64, nsec int64) Time

func (t Time) Format(layout string) string

該轉換主要分三步:

1、 將時間戳型別轉成 int64 型別

2、將 int64 型別時間戳轉換成 Time 結構

3、呼叫 Time 結構體的 Format 函式

示例程式碼:

// 1、將時間戳轉換成int64型別
timestamps := int64(1609945385) //該時間戳代表2021-01-06 23:03:05

//2、將int64型別時間戳轉換成Time結構,time.Unix函式的第2個引數代表納秒數
t := time.Unix(timestamps, 0)

//3、呼叫Time結構體的Format函式,這裡我們定義一組格式
var formats = []string{
    "2006年01月02日 15時04分05秒",
    "2006-01-02 15:04:05",
    "2006/01/02 15:04:05",
    "06-01-02",
    "06年01月02日",
    "2006.01.02",
    "06/1/2",
}

for _, layout := range formats {
    result := t.Format(layout)
    fmt.Printf("日期格式:%s, 轉換結果:%s \n", layout, result)
}

2、日期字串按格式轉換成時間戳

函式原型:funcParseInLocation(layout, valuestring, loc *Location) (Time,error)

該轉換主要分三步:

1、呼叫 time.LoadLocation 函式,設定特定的時區。否則,在第 2 步,預設會按 UTC 時區解析時間。 2、呼叫 time.ParseInLocation 函式,將字串轉換成 Time 結構體 3、呼叫 Time 結構體的 Unix 函式轉換成對應的時間戳

示例程式碼:

// 該結構體代表將value按format格式解析成Time結構體例項
type ParseFormat struct {
    format string // 日期格式
    value string // 要轉換的日期
}
//這裡定義一組時間格式和要轉換的日期字串
var parseFormats = []ParseFormat{
    {"2006年01月02日 15時04分05秒", "2021年01月06日 23時03分05秒"},

    {"2006-01-02 15:04:05", "2021-01-06 23:03:05"},

    {"2006/01/02 15:04:05", "2021/01/06 23:03:05"},

    {"06-01-02", "21-01-06"},

    {"06年01月02日", "21年01月06日"},

    {"2006.01.02", "2021.01.06"},

    {"06/1/2", "21/1/6"},
}

//1、設定時區為上海,即北京時間
loc, _ := time.LoadLocation("Asia/Shanghai")

for _, parseFormat := range parseFormats {
    // 2、將日期字串按特定格式轉換成特定時區下的Time結構體
    t, _ := time.ParseInLocation(parseFormat.format, parseFormat.value, loc)

    // 3、呼叫Time結構體的Unix函式轉換成對應的時間戳
    unix := t.Unix()
    fmt.Printf("時區:%v, 時間戳(秒):%d\n", t.Location(), unix)
}

03 時間之間的常用計算操作

這裡介紹一個新的資料型別 Duration。在 time 原始碼包中的定義如下:

type Duration int64

Duration,代表的是兩個時間點之間的持續時間(納秒數),即時段。

上文的 Time 結構體型別,代表的是時刻,即一個時間點。如下圖:

Duration = t1 - t2 單位:納秒

1、計算兩個日期之間相差多少秒

該轉換主要分三步:

1、呼叫 time.LoadLocation 函式,設定特定的時區。否則,第 2 步預設會按 UTC 時區解析時間。

2、呼叫 time.ParseInLocation 函式,將字串轉換成 Time 結構體

3、呼叫 Time 結構體的計算函式 Sub,得到兩個時間之間的 Duration

示例程式碼:

t1str := "2021-01-07 15:57:23"
t2str := "2021-01-07 18:57:23"
layout := "2006-01-02 15:04:05" //時間字串的格式
//1、將時間字串轉換成Time型別
location, _ := time.LoadLocation("Asia/Shanghai")
t1 := time.ParseInLocation(layout, t1str, location)
t2 := time.ParseInLocation(layout, t2str, location)

//2、計算兩個Time結構例項之間的差
d := t2.Sub(t1)

//3、根據返回的Duration型別的d轉換成相應的小時/分鐘/秒數
hours := d.Hours() //轉換成兩個時刻相差的小時數
minutes := d.Minutes() //轉換成兩個時刻相差的分鐘數
seconds := d.Seconds() //轉換成兩個時刻相差的秒數
milliseconds := d.Milliseconds() //轉換成兩個時刻相差的毫秒數
microseconds := d.Microseconds() //轉換成兩個時刻相差的微妙數
nanoseconds := d.Nanoseconds() //轉換成兩個時刻相差的納秒數

2、獲取從某個時間 至今 經過的時間 Duration

函式原型:funcSince(t Time) Duration

場景:假設你和你女朋友相識於 2014-10-02 13:14:15,計算出至今你們總共認識了多長時間。

示例程式碼:

t1str := "2014-10-02 13:14:15"
layout := "2006-01-02 15:04:05" //時間字串的格式
//1、將時間字串轉換成Time型別
location, _ := time.LoadLocation("Asia/Shanghai")
t := time.ParseInLocation(layout, t1str, location)

//2、計算兩個Time結構例項之間的差
d := time.Since(t)

//2、根據返回的d轉換成響應的小時/分鐘/秒數
hours := d.Hours() //轉換成兩個時刻相差的小時數
minutes := d.Minutes() //轉換成兩個時刻相差的分鐘數
seconds := d.Seconds() //轉換成兩個時刻相差的秒數
milliseconds := d.Milliseconds() //轉換成兩個時刻相差的毫秒數
microseconds := d.Microseconds() //轉換成兩個時刻相差的微妙數
nanoseconds := d.Nanoseconds() //轉換成兩個時刻相差的納秒數
fmt.Printf("從%s至今你們一起度過了共%d", t1str, d.Round(24*time.Hour))
fmt.Printf("從%s至今共一起度過了%f小時\n", t1str, time.Now().Format(layout), hours)

3、計算從今天到未來某個時間經過的時間

函式原型:funcUntil(t Time) Duration

示例程式碼:

t1str := "2021-12-21 13:14:15"
layout := "2006-01-02 15:04:05" //時間字串的格式
//第1步,將時間字串轉換成Time型別
location, _ := time.LoadLocation("Asia/Shanghai")
t := time.ParseInLocation(layout, t1str, location)

//第2步,計算兩個Time結構例項之間的差
d := time.Until(t)

//第3步,根據返回的d轉換成響應的小時/分鐘/秒數
hours := d.Hours() //轉換成兩個時刻相差的小時數
fmt.Printf("距女朋友生日%s還有%f小時\n", t1str, hours)

4、時間之間的比較:是早、是晚、還是相等

相關函式:

func (t Time) After(u Time) bool

func (t Time) Before(u Time) bool

func (t Time) Equal(u Time) bool

場景:你和女朋友約會,約好 2021-12-12 13:14:15 在餐廳門口見。這時,你看了看手錶,在大腦中和約定時間快速的比較了下,判斷是來早了還是來晚了

pivot := "2021-12-12 13:14:15"
layout := "2006-01-02 15:04:05" //時間字串的格式
//第1步,將時間字串轉換成Time型別
location, _ := time.LoadLocation("Asia/Shanghai")
pivotT := time.ParseInLocation(layout, t1str, location)

//第2步,獲取現在的時間
t := time.Now()

//第3步,和約定時間比較下是否來早了
if t.Before(pivotT) {
    fmt.Println("來早了")
}

//和約定時間比較一下,看是否來晚了
if t.After(pivotT) {
    fmt.Println("oh,糟糕,來晚了")
}

//和約定時間比較一下,一看,剛剛好
if t.Equal(pivotT) {
    fmt.Println("還好,還好,剛剛好")
}

5、計算 N 天后的時間

函式原型:func(t Time) Add(d Duration) Time

場景:有一天,你女朋友說,3 天后去你家裡玩。你趕緊在日曆上看看 3 天后的日期,做上了標記。

d := 3 * 24 * time.Hour

afterNDay := time.Now().Add(d)

fmt.Println("3天后的日期是", afterNDay.Format("2006-01-02"))

04 總結

golang 中,Time 和 Duration 型別是時間相互轉換的載體。時間字串格式化時的格式必須以 2006-01-02 15:14:15 這個時間為模板進行格式化。使用該時間的原因是在 Posix date 命令中是 1 2 3 4 5 6。如下:

Mon Jan 2 15:04:05 -0700 MST 2006
0   1   2  3  4  5              6
更多原創文章乾貨分享,請關注公眾號
  • golang 中 time 包使用教程之基礎使用篇
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章