<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Golang基礎(chǔ)筆記十一之日期與時(shí)間處理

      本文首發(fā)于公眾號(hào):Hunter后端

      原文鏈接:Golang基礎(chǔ)筆記十一之日期與時(shí)間處理

      本篇筆記介紹 Golang 里日期與時(shí)間的處理,以下是本篇筆記目錄:

      1. 當(dāng)前日期與時(shí)間的獲取
      2. 字符串與時(shí)間格式的互相轉(zhuǎn)換
      3. 時(shí)間戳與時(shí)間格式的互相轉(zhuǎn)換
      4. 日期與時(shí)間的加減
      5. 星期數(shù)的獲取
      6. 定時(shí)器與計(jì)時(shí)器

      1、當(dāng)前日期與時(shí)間的獲取

      在 Golang 里,日期和時(shí)間處理都通過 time 包來實(shí)現(xiàn)。

      如果我們想獲取當(dāng)前時(shí)間,我們可以使用 time.Now() 來操作:

      now := time.Now()
      fmt.Println(now)  // 2025-06-29 12:29:16.112605 +0800 CST m=+0.000154626
      

      如果我們想獲取單獨(dú)的年月日時(shí)分秒字段,可以使用下面的操作:

      now := time.Now()
      
      year, month, day := now.Date()
      hour, minute, second := now.Clock()
      
      fmt.Println(year, month, day)  // 2025 June 29
      fmt.Println(hour, minute, second)  // 15 29 50
      

      可以看到輸出的月份是 June,但實(shí)際上月份是一個(gè)自定義的類型 Month,本質(zhì)上也是一個(gè) int 型數(shù)據(jù),其源代碼如下:

      type Month int
      
      const (
          January Month = 1 + iota
          February
          March
          April
          May
          June
          July
          August
          September
          October
          November
          December
      )
      

      所以,對(duì)于這里的年月日時(shí)分秒的單個(gè)變量,我們想將其組合輸出為一般的 %Y-%m-%d %H:%M:%S 格式,可以如下操作:

      fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
      

      我們也可以分別單獨(dú)獲取對(duì)應(yīng)的年月日時(shí)分秒數(shù)據(jù):

      now := time.Now()
      
      fmt.Println(now.Year())
      fmt.Println(now.Month())
      fmt.Println(now.Day())
      fmt.Println(now.Hour())
      fmt.Println(now.Minute())
      fmt.Println(now.Second())
      

      2、字符串與時(shí)間格式的互相轉(zhuǎn)換

      1. 時(shí)間格式轉(zhuǎn)字符串

      在其他計(jì)算機(jī)語言中,如果想將時(shí)間字段轉(zhuǎn)化為字符串,格式化的操作比如 Python,一般是類似于 %Y-%m-%d %H:%M:%S 這種,但是 Golang 里是一個(gè)特殊的格式化字段,為 2006-01-02 15:04:05

      Go 里對(duì)時(shí)間字段格式化的函數(shù)為 Format(),下面是將時(shí)間格式轉(zhuǎn)為字符串的操作為:

      now := time.Now()
      
      fmt.Println(now.Format("2006-01-02 15:04:05")) // 2025-06-29 22:45:11
      

      當(dāng)然,格式化操作也可以單獨(dú)針對(duì)日期,或者時(shí)間,連接的符號(hào)也可以自定義:

      now := time.Now()
      
      fmt.Println(now.Format("2006/01/02"))  // 2025/06/29
      fmt.Println(now.Format("15:04:05"))  // 23:22:06
      

      2. 字符串轉(zhuǎn)時(shí)間格式

      字符串轉(zhuǎn)時(shí)間格式使用 time.Parse() 函數(shù),以下是一個(gè)測試:

      timeStr := "2025/06/29"
      
      t, err := time.Parse("2006/01/02", timeStr)
      if err != nil {
          fmt.Println("str to time error: ", err)
      } else {
          fmt.Println("str to time is: ", t)
      }
      
      // str to time is:  2025-06-29 00:00:00 +0000 UTC
      

      在這里 time.Parse() 返回兩個(gè)字段,一個(gè)是轉(zhuǎn)換后的時(shí)間字段,一個(gè)是轉(zhuǎn)換過程中的錯(cuò)誤。

      上面是轉(zhuǎn)換日期,轉(zhuǎn)換時(shí)間也是一樣的操作:

      timeStr = "20:24:24"
      
      t, err := time.Parse("15:04:05", timeStr)
      if err != nil {
          fmt.Println("str to time error: ", err)
      } else {
          fmt.Println("str to time is: ", t)
      }
      
      // str to time is:  0000-01-01 20:24:24 +0000 UTC
      

      而如果提供了錯(cuò)誤的時(shí)間字符串,返回的 err 字段則不會(huì)為空,比如下面這個(gè)示例:

      timeStr := "2025/13/29"
      
      t, err := time.Parse("2006/01/02", timeStr)
      if err != nil {
          fmt.Println("str to time error: ", err)
      } else {
          fmt.Println("str to time is: ", t)
      }
      
      // str to time error:  parsing time "2025/13/29": month out of range
      

      3、時(shí)間戳與時(shí)間格式的互相轉(zhuǎn)換

      另一個(gè)在時(shí)間函數(shù)中常用到的用于轉(zhuǎn)換的數(shù)據(jù)是時(shí)間戳,下面介紹一下時(shí)間戳與時(shí)間的互相轉(zhuǎn)換。

      1. 時(shí)間格式轉(zhuǎn)換為時(shí)間戳

      下面是時(shí)間格式轉(zhuǎn)換為秒級(jí)的時(shí)間戳:

      now := time.Now()
      
      fmt.Println(now.Unix())  // 1751211429
      

      還有轉(zhuǎn)換為毫秒,納秒級(jí)的操作:

      now := time.Now()
      
      fmt.Println(now.UnixMilli())  // 1751211522339
      fmt.Println(now.UnixNano())  // 1751211522339955000
      

      2. 時(shí)間戳轉(zhuǎn)換為時(shí)間格式

      時(shí)間戳轉(zhuǎn)換為時(shí)間格式的函數(shù)為 time.Unix()

      timestamp := 1751211429
      targetTime := time.Unix(int64(timestamp), 0)
      fmt.Println(targetTime)  // 2025-06-29 23:37:09 +0800 CST
      

      這里需要注意,輸入的時(shí)間戳需要是 int64 類型,輸入的第二個(gè)參數(shù)為納秒值,如果不需要那么精細(xì)的話,傳值為 0 即可。

      4、日期與時(shí)間的加減

      介紹日期與時(shí)間的加減,這里分為兩部分來介紹,一部分是時(shí)分秒,一部分是年月日,他們分別用到的函數(shù)是 Add()AddDate()

      1. Add()-時(shí)分秒的加減

      time.Duration

      Add() 函數(shù)的參數(shù)類型是 time.DurationDuration 也是自定義的一個(gè)時(shí)間單位,一納秒就是一個(gè) Duration,它的類型是 int64,范圍是:

      const (
          minDuration Duration = -1 << 63
          maxDuration Duration = 1<<63 - 1
      )
      

      而時(shí)分秒也都根據(jù)其轉(zhuǎn)換關(guān)系定義好了各自的字段:

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

      所以我們?cè)谑褂?Add() 函數(shù)的時(shí)候可以直接使用對(duì)應(yīng)的單位。

      時(shí)分秒的加減
      now := time.Now()
      
      threeHoursLater := now.Add(3 * time.Hour)
      thirtyMinutesAgo := now.Add(-30 * time.Minute)
      twoDaysLater := now.Add(48 * time.Hour)
      
      fmt.Println("now is: ", now.Format("2006-01-02 15:04:05"))
      fmt.Println("three hours later is: ", threeHoursLater.Format("2006-01-02 15:04:05"))
      fmt.Println("thirty minutes ago is: ", thirtyMinutesAgo.Format("2006-01-02 15:04:05"))
      fmt.Println("two days later is: ", twoDaysLater.Format("2006-01-02 15:04:05"))
      

      輸出結(jié)果如下:

      now is:  2025-06-30 22:58:38
      three hours later is:  2025-07-01 01:58:38
      thirty minutes ago is:  2025-06-30 22:28:38
      two days later is:  2025-07-02 22:58:38
      

      2. AddDate()-年月日的加減

      AddDate() 函數(shù)接收三個(gè)參數(shù),分別是 years、months、days,表示需要在當(dāng)前時(shí)間需要增加的年數(shù)、月數(shù)和天數(shù)。

      如果是想要回溯過去的日期,在對(duì)應(yīng)的參數(shù)前加上負(fù)號(hào) - 即可。

      如果是不需要指定的參數(shù)設(shè)為 0 即可。

      比如想要獲取今天前一個(gè)月的日期,以及今天往后三天的日期,可以如下操作:

      now := time.Now()
      
      lastMonth := now.AddDate(0, -1, 0)
      latestThreeDays := now.AddDate(0, 0, 3)
      
      fmt.Println("last month is: ", lastMonth.Format("2006-01-02 15:04:05"))
      fmt.Println("latest three days is: ", latestThreeDays.Format("2006-01-02 15:04:05"))
      

      3. Add() 和 AddDate() 使用示例

      這里分別使用 Add()AddDate() 兩個(gè)函數(shù)打印出之后七天的日期,其操作如下:

      使用 Add() 函數(shù):

      now := time.Now()
      
      for i := range 7 {
          targetDate := now.Add(time.Duration(24*(i+1)) * time.Hour)
          fmt.Println(targetDate.Format("2006-01-02"))
      }
      

      使用 AddDate() 函數(shù):

      now := time.Now()
      
      for i := range 7 {
          targetDate := now.AddDate(0, 0, i+1)
          fmt.Println(targetDate.Format("2006-01-02"))
      }
      

      4. 兩個(gè)時(shí)間點(diǎn)的差值

      1) Sub()

      如果我們想獲取兩個(gè)時(shí)間點(diǎn)之間差值,比如用于測試某個(gè)函數(shù)執(zhí)行的時(shí)間,可以使用 Sub() 函數(shù),返回的結(jié)果也是 time.Duration

      t1 := time.Now()
      time.Sleep(3 * time.Second)
      t2 := time.Now()
      
      subResult := t2.Sub(t1)
      fmt.Println(subResult)  // 3.00144925s
      

      我們可以將 subResult 直接轉(zhuǎn)換成我們想要的單位,比如毫秒和分鐘:

      fmt.Println("use millseconds: ", subResult.Milliseconds())  // use millseconds:  3001
      fmt.Println("use minutes: ", subResult.Minutes())  // use minutes:  0.05002786111666667
      
      2) time.Since()

      如果我們想獲取現(xiàn)在距離某個(gè)時(shí)間點(diǎn)的差值,也可以直接使用 time.Since() 函數(shù),其使用示例如下:

      t1 := time.Now()
      time.Sleep(2 * time.Second)
      
      result := time.Since(t1)
      fmt.Println(result)  // 2.001462166s
      

      5、星期數(shù)的獲取

      我們也可以根據(jù)日期來獲取對(duì)應(yīng)的星期數(shù),比如今天是星期幾:

      now := time.Now()
      
      fmt.Println(now.Weekday())  // Monday
      

      輸出的信息是 Monday

      星期數(shù)的底層數(shù)據(jù)也是 int 型,但是 Golang 將其包了一層,自定義了一個(gè) Weekday 的類型:

      type Weekday int
      
      const (
          Sunday Weekday = iota
          Monday
          Tuesday
          Wednesday
          Thursday
          Friday
          Saturday
      )
      

      從周日開始到周六,分別是從 0 到 6,我們可以打印一下:

      now := time.Now()
      
      fmt.Printf("%s, %d\n", now.Weekday(), now.Weekday())  // Monday, 1
      

      6、定時(shí)器與計(jì)時(shí)器

      下面介紹一下 Golang 里 time 模塊的定時(shí)器和計(jì)時(shí)器如何使用。

      1. 定時(shí)器

      定時(shí)器有兩個(gè)寫法,一個(gè)是 time.NewTimer(),一個(gè)是 time.After(),接收的參數(shù)類型都是 time.Duration

      下面直接用代碼示例來介紹如何使用。

      1) time.NewTimer

      有一個(gè)需求,我們需要調(diào)用某個(gè)函數(shù),但是函數(shù)的執(zhí)行時(shí)長是不定的,而整體執(zhí)行的時(shí)長是有限的,我們希望能在指定的時(shí)間內(nèi)返回?cái)?shù)據(jù),如果這個(gè)函數(shù)執(zhí)行超時(shí)就不希望它再執(zhí)行了,能夠立即獲取其超時(shí)狀態(tài)。

      針對(duì)這個(gè)需求,我們就可以使用定時(shí)器來完成。

      首先,我們有一個(gè)需要執(zhí)行的函數(shù),這個(gè)函數(shù)可能是調(diào)用某個(gè)接口,可能是從 Redis 或者 MySQL 中讀數(shù)據(jù),但是其執(zhí)行時(shí)長是不定的,我們用 RandomTimeWork() 函數(shù)來替代,并且在其中設(shè)置一個(gè)隨機(jī)休息的時(shí)間用來模擬不定的執(zhí)行時(shí)長:

      func RandomTimeWork() int {
          sleepSeconds := rand.Intn(10)
          time.Sleep(time.Duration(sleepSeconds) * time.Second)
          return sleepSeconds
      }
      

      然后我們需要一個(gè)中間函數(shù)使用通道來傳遞其返回值:

      func CallFunc(ch chan int) {
          result := RandomTimeWork()
          ch <- result
      }
      

      接下來就是主函數(shù)的操作,我們需要先設(shè)置一個(gè)定時(shí)器,這里我們?cè)O(shè)置為 5 秒的超時(shí):

      timeout := time.NewTimer(5 * time.Second)
      

      然后設(shè)置一個(gè)通道用于傳輸數(shù)據(jù),并且使用 goroutine 來調(diào)用:

      ch := make(chan int)
      go CallFunc(ch)
      

      最后就是使用 select 操作來進(jìn)行等待,看是通道先返回?cái)?shù)據(jù),還是定時(shí)器先計(jì)時(shí)完畢:

      select {
      case result := <-ch:
          fmt.Println("call func success, sleep seconds: ", result)
      case <-timeout.C:
          fmt.Println("call func timeout")
      }
      

      其整體代碼如下:

      package main
      
      import (
          "fmt"
          "math/rand"
          "time"
      )
      
      func RandomTimeWork() int {
          sleepSeconds := rand.Intn(10)
          time.Sleep(time.Duration(sleepSeconds) * time.Second)
          return sleepSeconds
      }
      
      func CallFunc(ch chan int) {
          result := RandomTimeWork()
          ch <- result
      }
      
      func main() {
          timeout := time.NewTimer(5 * time.Second)
      
          ch := make(chan int)
          go CallFunc(ch)
      
          select {
          case result := <-ch:
              fmt.Println("call func success, sleep seconds: ", result)
          case <-timeout.C:
              fmt.Println("call func timeout")
          }
      }
      

      在上面的操作中,如果待執(zhí)行的函數(shù)先執(zhí)行完畢,而定時(shí)器卻沒有結(jié)束,我們可以手動(dòng)執(zhí)行停止定時(shí)器操作。

      實(shí)際上,如果不手動(dòng)停止,默認(rèn)等待定時(shí)器觸發(fā)結(jié)束或者程序完畢也可以,但是在高并發(fā)場景下,如果有很多未完成的定時(shí)器會(huì)造成內(nèi)存占用增加,且增加程序的 GC 負(fù)擔(dān),因此,我們可以選擇手動(dòng)提前停止定時(shí)器。

      停止操作也很簡單,在獲取到函數(shù)執(zhí)行的結(jié)果后,我們可以如下操作:

      select {
      case result := <-ch:
          fmt.Println("call func success, sleep seconds: ", result)
          timeout.Stop()
      case <-timeout.C:
          fmt.Println("call func timeout")
      }
      
      2) time.After

      除了 time.NewTimer(),我們可以使用更簡單的 time.After() 函數(shù)來執(zhí)行一個(gè)定時(shí)器,相對(duì)上面的完整示例,我們只改動(dòng) main 函數(shù)里代碼如下:

      func main() {
          ch := make(chan int)
          go CallFunc(ch)
      
          select {
          case result := <-ch:
              fmt.Println("call func success, sleep seconds: ", result)
          case <-time.After(5 * time.Second):
              fmt.Println("call func timeout")
          }
      }
      

      注意:使用 time.After() 有個(gè)問題就是不可以提前手動(dòng)結(jié)束定時(shí)器。

      2. 計(jì)時(shí)器

      計(jì)時(shí)器常用于定時(shí)任務(wù),比如每隔多長時(shí)間執(zhí)行某個(gè)動(dòng)作,用到的函數(shù)是 time.NewTicker,傳入的參數(shù)是 time.Duration

      比如我們想將某個(gè)函數(shù)設(shè)置為每隔三秒鐘執(zhí)行一次,我們可以如下操作:

      func TargetFunc() {
          fmt.Println("call target func at: ", time.Now().Format("2006-01-02 15:04:05"))
      }
      
      func CallFuncEntrance(ticker *time.Ticker) {
          // for t := range ticker.C {
          for range ticker.C {
              TargetFunc()
          }
      }
      
      func main() {
          ticker := time.NewTicker(3 * time.Second)
      
          go CallFuncEntrance(ticker)
      
          time.Sleep(10 * time.Second)
          ticker.Stop()
      }
      

      上面的示例中,開啟了一個(gè) goroutine 并將計(jì)時(shí)器作為參數(shù)傳入,每隔三秒鐘觸發(fā)一次目標(biāo)函數(shù) TargetFunc()

      并且在最后執(zhí)行了計(jì)時(shí)器的停止操作 ticker.Stop()

      在這里如果我們想重置計(jì)時(shí)器的間隔時(shí)間,可以使用 Reset() 操作:

      func main() {
          ticker := time.NewTicker(3 * time.Second)
      
          go CallFuncEntrance(ticker)
      
          time.Sleep(10 * time.Second)
          ticker.Reset(1 * time.Second)
          time.Sleep(4 * time.Second)
          ticker.Stop()
      }
      

      執(zhí)行 main 函數(shù)可以看到目標(biāo)函數(shù)執(zhí)行的時(shí)間間隔會(huì)從 3s 變成 1s。

      定時(shí)任務(wù)的其他實(shí)現(xiàn)方式

      除了這個(gè)操作用來執(zhí)行定時(shí)任務(wù)外,我們還可以使用 for{}time.Sleep() 操作來實(shí)現(xiàn)定時(shí)任務(wù),其示例如下:

      func TargetFunc() {
          fmt.Println("call target func at: ", time.Now().Format("2006-01-02 15:04:05"))
      }
      
      func CallFuncEntrance() {
          for {
              TargetFunc()
              time.Sleep(3 * time.Second)
          }
      }
      
      func main() {
          go CallFuncEntrance()
          time.Sleep(10 * time.Second)
      }
      
      posted @ 2025-07-14 22:23  XHunter  閱讀(610)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 久久久久久人妻一区精品| 欧美xxxxx高潮喷水| 兰西县| 色综合久久一区二区三区| 国产色无码专区在线观看| 国产99视频精品免费视频6| 亚洲精品欧美综合二区| 色爱区综合激情五月激情| 国产99视频精品免费观看9| 国产在线观看91精品亚瑟| 日韩精品一卡二卡三卡在线| 真实单亲乱l仑对白视频| 亚洲国产精品高清久久久| 夜夜夜高潮夜夜爽夜夜爰爰| 中文字幕无线码中文字幕免费 | 免费人成网站视频在线观看| 五台县| 99RE6在线观看国产精品| 久久久久免费看少妇高潮A片| 日韩乱码人妻无码中文字幕视频| 成人网站国产在线视频内射视频| 成人免费av在线观看| 中文字幕亚洲精品人妻| 亚洲熟女乱色一区二区三区| 亚洲国产精品特色大片观看完整版| 亚洲人成电影在线天堂色| 亚洲区一区二区激情文学| 性夜黄a爽影免费看| 成人网站免费观看永久视频下载| 久热这里只有精品12| 免费特黄夫妻生活片| 亚洲欧美成人一区二区三区| 国产福利酱国产一区二区| 97人人模人人爽人人喊网| 午夜精品福利一区二区三| 色狠狠色噜噜AV一区| 国产青榴视频在线观看| 国产亚洲一区二区三区四区| 国产成人av免费网址| 日本韩国日韩少妇熟女少妇| 日韩激情一区二区三区|