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

在編寫程序中,我們經常會遇到時間戳和日期字符串相互轉換、獲取當前時間、時間之間的比較操作。本文主要介紹 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() (year int, month Month, day int)

func (t Time) Clock() (hour, min, sec int)

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、日期字符串按格式轉換成時間戳

函數原型:

func ParseInLocation(layout, value string, 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、計算從今天到未來某個時間經過的時間 

函數原型:func Until(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"))
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-e-Mlyd9x2OyybCDGE2Pog