日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Go 学习笔记(48)— Go 标准库之 time (获取时/分/秒的单位值、标准时间和Unix时间转换、字符串时间和Time类型转换、时区转换、时间的加减/休眠)

發布時間:2023/11/27 生活经验 23 豆豆

1. 概要說明

import "time"

time 包提供了時間的顯示和測量用的函數。日歷的計算采用的是公歷。

Go 提供以下幾種時間類型:

  • 時間點 Time
  • 時間段 Duration
  • 時區 Location
  • Ticker
  • 定時器 Timer

2. Time 類型

type Time struct {// 內含隱藏或非導出字段
}

Time 代表一個納秒精度的時間點。

程序中應使用 Time 類型值來保存和傳遞時間,而不能用指針。就是說,表示時間的變量和字段,應為 time.Time 類型,而不是 *time.Time 類型。

時間點可以使用 Before 、 AfterEqual 方法進行比較。

  • Sub 方法讓兩個時間點相減,生成一個 Duration 類型值(代表時間段);
  • Add 方法給一個時間點加上一個時間段,生成一個新的Time類型時間點;

Time 零值代表時間點 January 1, year 1, 00:00:00.000000000 UTC。因為本時間點一般不會出現在使用中, IsZero 方法提供了檢驗時間是否顯式初始化的一個簡單途徑。

每一個時間都具有一個地點信息(及對應地點的時區信息),當計算時間的表示格式時,如 Format 、 HourYear 等方法,都會考慮該信息。 Local 、 UTCIn 方法返回一個指定時區(但指向同一時間點)的 Time 。修改地點/時區信息只是會改變其表示;不會修改被表示的時間點,因此也不會影響其計算。

2.1 Time 類型函數

2.1.1 func Date

func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

Date 返回一個時區為 loc 、當地時間為:
year-month-day hour:min:sec + nsec nanoseconds 的時間點。

代碼示例:

func main() {timeDate := time.Date(2020, 05, 23, 10, 11, 12, 13, time.Local)fmt.Printf("timeDate is %v, type is %T", timeDate, timeDate)// timeDate is 2020-05-23 10:11:12.000000013 +0800 CST, type is time.Time
}

2.1.2 func Now

func Now() Time

Now 返回當前本地時間。

代碼示例:

func main() {timeNow := time.Now()fmt.Printf("timeNow is %v, type is %T", timeNow, timeNow)// timeNow is 2020-05-23 10:23:11.061117 +0800 CST m=+0.005000301, type is time.Time
}

2.1.3 func Parse

func Parse(layout, value string) (Time, error)

Parse 解析一個格式化的時間字符串并返回它代表的時間。 layout 定義了參考時間:
Mon Jan 2 15:04:05 -0700 MST 2006,注意 layout 必須為 “2006-01-02 15:04:05”,否則會報錯誤:

parsing time "2020-05-22 10:25:30": month out of range

代碼示例:

func main() {timeParse, err := time.Parse("2006-01-02 15:04:05", "2020-05-22 10:25:30")if err != nil {fmt.Println("time parse failed: ", err)}fmt.Printf("timeParse is %v, type is %T", timeParse, timeParse)// timeParse is 2020-05-22 10:25:30 +0000 UTC, type is time.Time
}

2.1.4 func ParseInLocation

func ParseInLocation(layout, value string, loc *Location) (Time, error)

ParseInLocation 類似 Parse 但有兩個重要的不同之處:

  • 當缺少時區信息時, Parse 將時間解釋為 UTC 時間,而 ParseInLocation 將返回值的 Location 設置為 loc
  • 當時間字符串提供了時區偏移量信息時, Parse 會嘗試去匹配本地時區,而 ParseInLocation 會去匹配loc

代碼示例:

func main() {ParseInLocation, err := time.ParseInLocation("2006-01-02 15:04:05", "2020-05-22 10:25:30", time.Local)if err != nil {fmt.Println("time ParseInLocation failed: ", err)}fmt.Printf("ParseInLocation is %v, type is %T", ParseInLocation, ParseInLocation)// ParseInLocation is 2020-05-22 10:25:30 +0800 CST, type is time.Time
}

2.1.5 func Unix

func Unix(sec int64, nsec int64) Time

Unix 創建一個本地時間,對應 secnsec 表示的 Unix 時間(從January 1, 1970 UTC至該時間的秒數和納秒數)。
nsec 的值在 [0, 999999999] 范圍外是合法的。

代碼示例:

func main() {timeUnix := time.Unix(322020993, 3939993399848320)fmt.Printf("timeUnix is %v, type is %T", timeUnix, timeUnix)// timeUnix is 1980-05-01 00:43:06.39984832 +0800 CST, type is time.Time
}

以上的函數 DateNow 、 Parse 、 ParseInLocation 、 Unix 返回的都是 Time 類型的結構體。

2.2 Time 類型方法

Time 類型有很多結構體方法,如下表所示:

func (t Time) Location() *Location
func (t Time) Zone() (name string, offset int)
func (t Time) IsZero() bool
func (t Time) Local() Time
func (t Time) UTC() Time
func (t Time) In(loc *Location) Time
func (t Time) Unix() int64
func (t Time) UnixNano() int64
func (t Time) Equal(u Time) bool
func (t Time) Before(u Time) bool
func (t Time) After(u Time) bool
func (t Time) Date() (year int, month Month, day int)
func (t Time) Clock() (hour, min, sec int)
func (t Time) Year() int
func (t Time) Month() Month
func (t Time) ISOWeek() (year, week int)
func (t Time) YearDay() int
func (t Time) Day() int
func (t Time) Weekday() Weekday
func (t Time) Hour() int
func (t Time) Minute() int
func (t Time) Second() int
func (t Time) Nanosecond() int
func (t Time) Add(d Duration) Time
func (t Time) AddDate(years int, months int, days int) Time
func (t Time) Sub(u Time) Duration
func (t Time) Round(d Duration) Time
func (t Time) Truncate(d Duration) Time
func (t Time) Format(layout string) string
func (t Time) String() string
func (t Time) GobEncode() ([]byte, error)
func (t *Time) GobDecode(data []byte) error
func (t Time) MarshalBinary() ([]byte, error)
func (t *Time) UnmarshalBinary(data []byte) error
func (t Time) MarshalJSON() ([]byte, error)
func (t *Time) UnmarshalJSON(data []byte) error
func (t Time) MarshalText() ([]byte, error)
func (t *Time) UnmarshalText(data []byte) error

代碼示例如下:

func main() {nowTime := time.Now()fmt.Println("nowTime.Location", nowTime.Location())zoneName, _ := nowTime.Zone()fmt.Println("nowTime.Zone", zoneName)fmt.Println("nowTime.IsZero", nowTime.IsZero())fmt.Println("nowTime.Location", nowTime.Local())fmt.Println("nowTime.UTC", nowTime.UTC())fmt.Println("nowTime.In", nowTime.In(nowTime.Location()))fmt.Println("nowTime.Unix", nowTime.Unix())fmt.Println("nowTime.UnixNano", nowTime.UnixNano())fmt.Println("nowTime.Equal", nowTime.Equal(nowTime))fmt.Println("nowTime.Before", nowTime.Before(nowTime))fmt.Println("nowTime.After", nowTime.After(nowTime))fmt.Println(nowTime.Date())fmt.Println(nowTime.Clock())fmt.Println("nowTime.Year", nowTime.Year())fmt.Println("nowTime.YearDay", nowTime.YearDay())fmt.Println("nowTime.Month", nowTime.Month())fmt.Println(nowTime.ISOWeek())fmt.Println("nowTime.Day", nowTime.Day())fmt.Println("nowTime.Weekday", nowTime.Weekday())fmt.Println("nowTime.Hour", nowTime.Hour())fmt.Println("nowTime.Minute", nowTime.Minute())fmt.Println("nowTime.Second", nowTime.Second())fmt.Println("nowTime.Nanosecond", nowTime.Nanosecond())fmt.Println("nowTime.Add", nowTime.Add(time.Hour*3))fmt.Println("nowTime.AddDate", nowTime.AddDate(2, 3, 4))fmt.Println("nowTime.Sub", nowTime.Sub(nowTime))fmt.Println("nowTime.String", nowTime.String())fmt.Println("nowTime.Format", nowTime.Format("2006-01-02 15:04:05"))fmt.Println("nowTime.Format", nowTime.Format("2006-01-02 15-04-05"))fmt.Println("nowTime.Format", nowTime.Format("2006-01-02"))}

輸出結果:

nowTime.Location Local
nowTime.Zone CST
nowTime.IsZero false
nowTime.Location 2020-05-23 15:03:24.4848344 +0800 CST
nowTime.UTC 2020-05-23 07:03:24.4848344 +0000 UTC
nowTime.In 2020-05-23 15:03:24.4848344 +0800 CST
nowTime.Unix 1590217404
nowTime.UnixNano 1590217404484834400
nowTime.Equal true
nowTime.Before false
nowTime.After false
2020 May 23
15 3 24
nowTime.Year 2020
nowTime.YearDay 144
nowTime.Month May
2020 21
nowTime.Day 23
nowTime.Weekday Saturday
nowTime.Hour 15
nowTime.Minute 3
nowTime.Second 24
nowTime.Nanosecond 484834400
nowTime.Add 2020-05-23 18:03:24.4848344 +0800 CST m=+10800.007000401
nowTime.AddDate 2022-08-27 15:03:24.4848344 +0800 CST
nowTime.Sub 0s
nowTime.String 2020-05-23 15:03:24.4848344 +0800 CST m=+0.007000401
nowTime.Format 2020-05-23 15:03:24
nowTime.Format 2020-05-23 15-03-24
nowTime.Format 2020-05-23

3. Duration 類型

type Duration int64

Duration 類型代表兩個時間點之間經過的時間,以納秒為單位。

const (Nanosecond  Duration = 1Microsecond          = 1000 * NanosecondMillisecond          = 1000 * MicrosecondSecond               = 1000 * MillisecondMinute               = 60 * SecondHour                 = 60 * Minute
)

常用的時間段。沒有定義一天或超過一天的單元,以避免夏時制的時區切換的混亂。

要將 Duration 類型值表示為某時間單元的個數,用除法:

second := time.Second
fmt.Print(int64(second/time.Millisecond)) // prints 1000

要將整數個某時間單元表示為 Duration 類型值,用乘法:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

3.1 Duration 類型函數

3.1.1 func ParseDuration

func ParseDuration(s string) (Duration, error)

ParseDuration 解析一個時間段字符串。一個時間段字符串是一個序列,每個片段包含可選的正負號、十進制數、可選的小數部分和單位后綴,如"300ms"、"-1.5h"、“2h45m”。合法的單位有"ns"、“us” /“μs”、“ms”、“s”、“m”、“h”。

3.1.2 func Since

func Since(t Time) Duration

Since 返回從 t 到現在經過的時間,等價于 time.Now().Sub(t) 。

func test() {start := time.Now() // 獲取當前時間sum := 0for i := 0; i < 100000000; i++ {sum++}elapsed := time.Since(start)	// 等價于  elapsed := time.Now().Sub(start)fmt.Println("該函數執行完成耗時:", elapsed)
}

3.2 Duration 類型方法

ParseDuration 解析一個時間段字符串。一個時間段字符串是一個序列,每個片段包含可選的正負號、十進制數、可選的小數部分和單位后綴,如"300ms"、"-1.5h"、“2h45m”。
合法的單位有"ns"、“us”、“μs”、“ms”、“s”、“m”、“h”。

func (d Duration) Hours() float64
func (d Duration) Minutes() float64
func (d Duration) Seconds() float64
func (d Duration) Nanoseconds() int64
func (d Duration) String() string

代碼示例:

func main() {tp, _ := time.ParseDuration("120s")fmt.Println("tp.Hours", tp.Hours())             // tp.Hours 0.03333333333333333fmt.Println("tp.Minutes", tp.Minutes())         // tp.Minutes 2fmt.Println("tp.Seconds", tp.Seconds())         // tp.Seconds 120fmt.Println("tp.Nanoseconds", tp.Nanoseconds()) // tp.Nanoseconds 120000000000fmt.Println("tp.String", tp.String())           // tp.String 2m0s
}

4. Location 類型

func LoadLocation(name string) (*Location, error)
func FixedZone(name string, offset int) *Location
func (l *Location) String() string

代碼示例:

func main() {loc, _ := time.LoadLocation("")// 服務器設定的時區,一般為CSTloc, _ = time.LoadLocation("Local")fmt.Println("loc is ", loc) // loc is  Local// 美國洛杉磯PDTloc, _ = time.LoadLocation("America/Los_Angeles")fmt.Println("loc is ", loc) // loc is  America/Los_Angeles// 獲取指定時區的時間點local, _ := time.LoadLocation("America/Los_Angeles")fmt.Println(time.Date(2018, 1, 1, 12, 0, 0, 0, local)) //2018-01-01 12:00:00 -0800 PST}

5. 實際業務使用場景

5.1 獲取時、分、秒的單位值

const (Nanosecond  Duration = 1Microsecond          = 1000 * NanosecondMillisecond          = 1000 * MicrosecondSecond               = 1000 * MillisecondMinute               = 60 * SecondHour                 = 60 * Minute
)

源碼包定義以上常量,在代碼中可以通過 time.XXX 得到,代碼如下:

func main() {fmt.Println("time.Nanosecond", time.Nanosecond)   // time.Nanosecond 1nsfmt.Println("time.Microsecond", time.Microsecond) // time.Microsecond 1μsfmt.Println("time.Millisecond", time.Millisecond) // time.Millisecond 1msfmt.Println("time.Second", time.Second)           // time.Second 1sfmt.Println("time.Minute", time.Minute)           // time.Minute 1m0sfmt.Println("time.Hour", time.Hour)               // time.Hour 1h0m0s
}

5.2 標準時間和Unix時間轉換

代碼如下:

func main() {timeNow := time.Now()fmt.Println("timeNow is ", timeNow)// timeNow is  2020-05-23 22:29:53.0060736 +0800 CST m=+0.005000301timeUnix := timeNow.Unix()fmt.Println("timeUnix is ", timeUnix)// timeUnix is  1590244193timeCurrent := time.Unix(timeUnix, 0)fmt.Println("timeCurrent is ", timeCurrent)// timeCurrent is  2020-05-23 22:29:53 +0800 CST}

5.3 Time 類型轉換為字符串

注意: Go 中指定的特定時間格式為 2006-01-02 15:04:05 -0700 MST , 為了記憶方便,按照美式時間格式 月日時分秒年 外加時區 排列起來依次是 01/02 03:04:05PM ‘06 -0700,剛開始使用時需要注意

這一點與 Python 中的 %Y-%m-%d %H-%M-%S 有區別。

示例代碼:

const (//time formatFormatDay      = "2006-01-02"FormatSecond   = "2006-01-02 15:04:05"FormatMinute   = "2006-01-02 15:04"FormatOnlyHour = "15:04"
)func main() {timeFormatDay := time.Now().Format(FormatDay)fmt.Printf("timeFormatDay is %#v, type is %T\n", timeFormatDay, timeFormatDay)// timeFormatDay is "2020-05-23", type is stringtimeFormatSecond := time.Now().Format(FormatSecond)fmt.Println("timeFormatSecond is ", timeFormatSecond)// timeFormatSecond is  2020-05-23 22:44:26timeFormatMinute := time.Now().Format(FormatMinute)fmt.Println("timeFormatMinute is ", timeFormatMinute)// timeFormatMinute is  2020-05-23 22:44timeFormatOnlyHour := time.Now().Format(FormatOnlyHour)fmt.Println("timeFormatOnlyHour is ", timeFormatOnlyHour)// timeFormatOnlyHour is  22:44}

5.4 字符串轉換為Time類型

代碼如下:

const (//time formatFormatDay      = "2006-01-02"FormatSecond   = "2006-01-02 15:04:05"FormatMinute   = "2006-01-02 15:04"FormatOnlyHour = "15:04"
)func main() {timestamp, _ := time.Parse(FormatSecond, "2020-05-23 22:20:30")fmt.Printf("timestamp is %v, type is %T\n", timestamp, timestamp)// timestamp is 2020-05-23 22:20:30 +0000 UTC, type is time.Timefmt.Println(timestamp.Unix()) //時間戳 1590272430fmt.Println(time.Date(2020, 05, 23, 10, 11, 12, 13, time.Local).Unix())}

5.5 時區變更后獲取時間戳

示例代碼:

const (//time formatFormatDay      = "2006-01-02"FormatSecond   = "2006-01-02 15:04:05"FormatMinute   = "2006-01-02 15:04"FormatOnlyHour = "15:04"
)func main() {loc, _ := time.LoadLocation("Asia/Shanghai")t, _ := time.ParseInLocation(FormatSecond, "2020-05-23 22:20:30", loc)fmt.Printf("t is %v, type is %T\n", t, t)// 標準時間格式 t is 2020-05-23 22:20:30 +0800 CST, type is time.Timefmt.Println(t.Unix()) //時間戳 1590243630}

5.6 比較兩個時間點

      dt := time.Date(2018, 1, 10, 0, 0, 1, 100, time.Local)fmt.Println(time.Now().After(dt))     // truefmt.Println(time.Now().Before(dt))    // false// 是否相等 判斷兩個時間點是否相等時推薦使用 Equal 函數fmt.Println(dt.Equal(time.Now()))

5.7 時區之間轉換

      // time.Local 用來表示當前服務器時區// 自定義地區時間secondsEastOfUTC := int((8 * time.Hour).Seconds())beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)fmt.Println(time.Date(2018,1,2,0,0,0,0, beijing))  // 2018-01-02 00:00:00 +0800 Beijing Time  // 當前時間轉為指定時區時間fmt.Println(time.Now().In(beijing))// 指定時間轉換成指定時區對應的時間dt, err := time.ParseInLocation("2006-01-02 15:04:05", "2017-05-11 14:06:06", time.Local)// 當前時間在零時區年月日   時分秒  時區year, mon, day := time.Now().UTC().Date()     // 2018 April 24 hour, min, sec := time.Now().UTC().Clock()    // 3 47 15zone, _ := time.Now().UTC().Zone()            // UTC

5.8 基于當前時間的加減

      now := time.Now()// 一年零一個月一天之后fmt.Println(now.Date(1,1,1))// 一段時間之后fmt.Println(now.Add(time.Duration(10)*time.Minute))// 計算兩個時間點的相差天數dt1 = time.Date(dt1.Year(), dt1.Month(), dt1.Day(), 0, 0, 0, 0, time.Local)dt2 = time.Date(dt2.Year(), dt2.Month(), dt2.Day(), 0, 0, 0, 0, time.Local)fmt.Println(int(math.Ceil(dt1.Sub(dt2).Hours() / 24)))

5.9 時間差值

      dt1 := time.Date(2018, 1, 10, 0, 0, 1, 100, time.Local)dt2 := time.Date(2018, 1, 9, 23, 59, 22, 100, time.Local)// 不用關注時區,go會轉換成時間戳進行計算fmt.Println(dt1.Sub(dt2))        

5.10 時間運算

      // func Sleep(d Duration)   休眠多少時間,休眠時處于阻塞狀態,后續程序無法執行time.Sleep(time.Duration(10) * time.Second)// func After(d Duration) <-chan Time  非阻塞,可用于延遲time.After(time.Duration(10) * time.Second)// func Since(t Time) Duration 兩個時間點的間隔start := time.Now()fmt.Println(time.Since(start))   // 等價于 Now().Sub(t), 可用來計算一段業務的消耗時間func Until(t Time) Duration     //  等價于 t.Sub(Now()),t與當前時間的間隔// func (t Time) Add(d Duration) Timefmt.Println(dt.Add(time.Duration(10) * time.Second))   // 加func (t Time) Sub(u Time) Duration                    // 減 // func (t Time) AddDate(years int, months int, days int) Timefmt.Println(dt.AddDate(1, 1, 1))func (t Time) Before(u Time) boolfunc (t Time) After(u Time) boolfunc (t Time) Equal(u Time) bool          比較時間點時盡量使用Equal函數 

6. time.After 一段時間后

由于 Go 語言中的通道和 goroutine 的設計,定時任務可以在 goroutine 中通過同步的方式完成,也可以通過在 goroutine 中異步回調完成。

  • 同步調用
func doTask() {fmt.Println("I am running")
}
func main() {// 定時器超時之后,執行后的的函數time.AfterFunc(time.Duration(3)*time.Second, doTask)time.Sleep(10 * time.Second)
}
  • 異步調用
func main() {// 聲明一個退出用的通道exit := make(chan int)fmt.Println("start")// 調用 time.AfterFunc()函數,傳入等待的時間和一個回調。回調使用一個// 匿名函數,在時間到達后, 匿名函數會在另外一個 goroutine 中被調用。time.AfterFunc(time.Second, func() {// 1秒后,打印結果fmt.Println("one second after")// 通知main的goroutine已經結束exit <- 0})// 等待結束<-exit
}

time.AfterFunc 函數是在 time.After 基礎上增加了到時的回調,方便使用。而 time.After 函數又是在 time.NewTimer() 函數上進行的封裝。

7. 定點計時

  • 計時器( Timer )的原理和倒計時鬧鐘類似,都是給定多少時間后觸發。
  • 打點器( Ticker )的原理和鐘表類似,鐘表每到整點就會觸發。

這兩種方法創建后會返回time.Timer 對象和 time.Ticker 對象,里面通過一個 C 成員 , 類型是只能接收的時間通道 C <-chan Time ),使用這個通道就可以 獲得時間觸發的通知。

使用 time.Ticker 可讓代碼每隔特定的時間就重復執行一次。需要在很長的時間內定期執行任務時,這么做很有用。

示例代碼 1:

func main() {// 定時休眠 1sFormatSecond := "2006-01-02 15:04:05"for {select {case <-time.NewTimer(1 * time.Second).C: // 將在1秒可讀,返回fmt.Println(time.Now().Format(FormatSecond), "sleep 1s")}}
}

輸出結果:

2021-04-19 14:12:59 sleep 1s
2021-04-19 14:13:00 sleep 1s
2021-04-19 14:13:01 sleep 1s
2021-04-19 14:13:02 sleep 1s
2021-04-19 14:13:03 sleep 1s
2021-04-19 14:13:04 sleep 1s
2021-04-19 14:13:05 sleep 1s

示例代碼 2:

package mainimport ("fmt""time"
)func main() {// 創建一個計時器,2秒后觸發stopper := time.NewTimer(time.Second * 2)// 創建一個斷續器,每500毫秒觸發一次ticker := time.NewTicker(time.Millisecond * 500)var i int// 每次觸發后 select會結束, 需要使用循環再次從打點器返回的通道中獲取觸發通知for {// 多路復用通道 同時等待多路計時器信號select {case <-stopper.C: // 計時器到時了fmt.Println("stop")// 跳出循環goto StopHerecase <-ticker.C: // 斷續器觸發了// 記錄觸發了多少次i++fmt.Println("tick", i)}}// 退出的標簽,使用goto跳轉
StopHere:fmt.Println("done")
}

輸出結果:

tick 1
tick 2
tick 3
stop
done

參考:
https://segmentfault.com/a/1190000015040923?utm_source=tag-newest
https://blog.csdn.net/wschq/article/details/80114036
https://studygolang.com/static/pkgdoc/pkg/time.htm

https://blog.csdn.net/duqiming/article/details/89393812

總結

以上是生活随笔為你收集整理的Go 学习笔记(48)— Go 标准库之 time (获取时/分/秒的单位值、标准时间和Unix时间转换、字符串时间和Time类型转换、时区转换、时间的加减/休眠)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。