time

Go內(nèi)置的time包提供了時間顯示和測量的函數(shù)

  • 時間可分為時間點和時間段箱亿,為此Go提供了兩種基礎數(shù)據(jù)類型time.Timetime.Duration
  • 所有與時間相關的業(yè)務都是基于時間點而衍生的惠爽,兩個時間點組成一個時間段。
  • 時間包括時間值和時區(qū)瞬哼,沒有包含時區(qū)信息的時間是不完整的婚肆、有歧義的。
  • 日歷的計算采用的是公歷
  • Go提供針對某些特定業(yè)務提供了諸如go.Location時區(qū)倒槐、go.Timer定時器...
功能 描述
time.Time 時間點
time.Duration 時間段
time.Location 時區(qū)
time.Timer 定時器
time.Ticker 周期觸發(fā)定時的計時器
time.C 存放時間點的管道

時間類型

time包提供了一個數(shù)據(jù)類型time.Time用來表示時間旬痹,時間一般包含時間值和時區(qū)兩部分,時間值是一個納秒精度的時間點讨越。

package time

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

time.Time結構包含三個字段:

字段 類型 描述
wall uint64 墻上時鐘两残,表示距離公元1年1月1日00:00:00UTC的秒數(shù)。
ext int64 時間模式把跨,表示納秒人弓。
loc *time.Location 時區(qū),處理偏移量着逐。不同時區(qū)對應的時間也不同崔赌。

最準確的時間計算是使用“原子振蕩周期”所計算的物理時鐘(Atomic Clock,原子鐘)耸别,又被定義為標準時間(International Atomic Time)健芭。常用的UTC(Universal Time Coordinated,世界協(xié)調(diào)時間)就是利用原子鐘為基準定義出來的秀姐,UTC標準時間以GMT(Greenwich Mean Time慈迈,格林威治時間)這個時區(qū)為基準。

本地時間 = UTC + 時區(qū)差
北京時間 = UTF + 8個小時

操作系統(tǒng)中存在兩個不同的時鐘省有,分別是單調(diào)時鐘(monotonic time)痒留、墻上時鐘(wall time/real time)

  • 單調(diào)時鐘是本機硬件的節(jié)拍數(shù),不同機器沒有可比性蠢沿。由于石英鐘本身的誤差伸头,時間會有閏秒等原因,因此單調(diào)時鐘與墻上時鐘是不一致的舷蟀。
  • 墻上時鐘又稱為時鐘時間恤磷,是進程運行的時鐘總量,其值與系統(tǒng)中同時運行的進程數(shù)量有關野宜。進程從開始運行到結束碗殷,時鐘走過的時間,包括進程在阻塞和等待狀態(tài)的時間速缨。
墻上時鐘 大小
flag 1位
時間戳 33位
納秒 30位

時間模式分為:是否包含單調(diào)時鐘锌妻、外部輸入的時間

  • 若時間模式ext包含單調(diào)時鐘,則wall字段中會存在一個時間戳秒代表墻上時鐘和一個時間戳納秒代表墻上時鐘旬牲。
  • 若時間模式ext不包含單調(diào)時鐘仿粹,則wall字段中會包含一個時間戳納秒代表墻上時鐘,ext字段則包含一個時間戳秒代表墻上時鐘原茅。

當前時間

  • time.Now()會返回當前本地時間對象
func Now() Time

例如:獲取當前本地時間信息

t := time.Now()
fmt.Println(t) // 2021-12-28 13:10:36.5987998 +0800 CST m=+0.003958401

從時間對象中獲取時間分量信息

時間分量 描述
t.Year()
t.Month()
t.Day()
t.Hour() 小時數(shù)
t.Minute() 分鐘
t.Second() 秒數(shù)
t.Nanosecond() 納秒吭历,1毫秒 = 1000納秒, 1秒 = 1000毫秒
t.Weekday() 星期幾
t.YearDay() 一年中的第n天
t.Zone() 獲取時區(qū)
t := time.Now()
fmt.Println(t)                                  // 2021-12-28 13:43:30.9266336 +0800 CST m=+0.004069101
fmt.Printf("Year = %d\n", t.Year())             // 2021
fmt.Printf("Month = %d\n", t.Month())           // 12
fmt.Printf("Day = %d\n", t.Day())               // 28
fmt.Printf("Hour = %d\n", t.Hour())             // 13
fmt.Printf("Minute = %d\n", t.Minute())         // 43
fmt.Printf("Second = %d\n", t.Second())         // 30
fmt.Printf("NanoSecond = %d\n", t.Nanosecond()) // 926633600
fmt.Printf("Weekday = %d\n", t.Weekday())       // 2
fmt.Printf("YearDay = %d\n", t.YearDay())       // 362
fmt.Println(t.Zone())                           // CST 28800

時間解析

time.Parse()會將字符串類型的日期時間轉換為UTC標準的Time類型

package time

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

例如:將字符串"2021-01-04 12:00:00"轉換為標準UTC的time.Time類型

t, err := time.Parse("2006-01-02 15:04:05", "2021-01-04 12:00:00")
if err != nil {
    panic(err)
}
fmt.Printf("%T\n", t)  // time.Time
fmt.Printf("%+v\n", t) // 2021-01-04 12:00:00 +0000 UTC

時間戳

UNIX時間戳(UNIX Timestamp)

  • Unix時間又稱為POSIX時間擂橘,是UNIX或類UNIX操作系統(tǒng)使用的時間表示方式晌区。
  • Unix時間表示從UTC的1970年1月1日0時0分0秒開始到現(xiàn)在的總秒數(shù),不考慮閏秒。
func (t Time) Unix() int64
func (t Time) UnixNano() int64
時間戳 單位 長度
t.Unix() 10位
t.UnixNano() 納秒 19位
s := t.Unix()
ns := t.UnixNano()
ms := t.UnixNano() / 1e6
fmt.Printf("timestamp = %d, unixnano = %d, ms = %d\n", s, ns, ms)
timestamp = 1618738171, unixnano = 1618738171513428200, ms = 1618738171513

19位納秒轉13位毫秒

ms := t.UnixNano() / 1e6
fmt.Println(ms) // 1618737494948
  • time.Unix()函數(shù)可將時間戳轉換為時間點對象
func time.Unix(sec int64, nsec int64) time.Time

時間格式

time.Format()用于獲取時間并格式化為字符串朗若,格式化占位符2006-01-02 15:04:05表示GoLang誕生時間恼五,此處為固定寫法。

func (t Time) Format(layout string) string

例如:將時間點對象轉換為指定格式的字符串

t := time.Now()
fmt.Println(t)//2021-04-18 17:53:23.8149167 +0800 CST m=+0.002995001

str := t.Format("2006-01-02 15:04:05")
fmt.Println(str)//2021-04-18 17:53:23

例如:將時間戳轉換為指定格式的字符串

ts := time.Now().Unix()
fmt.Println(ts)//1618739719

str := time.Unix(ts,0).Format("2006-01-02 15:04:05")
fmt.Println(str)//2021-04-18 17:55:19

標準時間

  • UTC(Coordinated Universal Time哭懈,協(xié)調(diào)世界時)是最主要的世界時間標準灾馒,它以原子時秒長為基礎,在時刻上盡量接近于格林尼治標準時間(Greenwich Mean Time遣总,GMT)睬罗。
  • UTC是世界上調(diào)節(jié)時鐘和時間的主要時間標準,它與0度經(jīng)線的平太陽時相差不超過1秒旭斥,且不遵守夏令時容达。
  • UTC是最接近格林威治標準時間(GMT)的替代時間系統(tǒng)之一,對于大多數(shù)用途來說垂券,UTC時間被認為與GMT時間互換花盐,但GMT時間已不再被科學界所確定。
func (t Time) UTC() Time 

例如:將GMT格林威治時間轉換為UTC時間

t := time.Now()
fmt.Println(t)//2021-04-18 17:57:51.7228428 +0800 CST m=+0.002020201

utc := t.UTC()
fmt.Println(utc)//2021-04-18 09:57:51.7228428 +0000 UTC

時區(qū)

時間其實包括時間值和時區(qū)圆米,沒有時區(qū)信息的時間是不完整的卒暂。使用沒有時區(qū)的非標準時間表示格式是有隱患的,由于解析時會根據(jù)使用場景的默認設置娄帖,如系統(tǒng)時區(qū)也祠、數(shù)據(jù)庫默認時區(qū)等,可能會引發(fā)事故近速。因此需確保服務器系統(tǒng)诈嘿、數(shù)據(jù)庫、應用程序時間統(tǒng)一的時區(qū)削葱。

time包存在兩個時區(qū)變量分別是time.UTC即UTC時間奖亚、time.Local本地時間

time.Location()函數(shù)返回時間點對象的地點和時區(qū)信息

func (t Time) Location() *Location

例如:獲取時間點對應的時區(qū)

t := time.Now()
loc := t.Location()
fmt.Println(loc)//Local

time.LoadLocation()用于獲取給定名字創(chuàng)建的時區(qū)

func time.LoadLocation(name string) (*time.Location, error)

例如:獲取服務器所在時區(qū)

loc,err := time.LoadLocation("Asia/Shanghai")
if err!=nil {
    println(err)
}
println(loc)//0xc0000c2000

是否能夠拿到時區(qū)取決于機器本地的zoneinfo文件,time.LoadLocation()函數(shù)將會返回一個*time.Location指針對象析砸。

計時器

time.Ticker

time.Ticker是一個周期觸發(fā)定時的計時器昔字,一旦被定義每隔一段時間會自動觸發(fā)。

type Ticker struct {
    C <-chan Time // 周期性傳遞時間信息的通道
    r runtimeTimer
}

time.Ticker會按照一個指定的時間間隔重復的向通道C發(fā)送系統(tǒng)當前時間值首繁,通道的接收者可以按固定的時間間隔從通道中讀取事件作郭。

//實現(xiàn)原理
go func(t *time.Ticker){
    for{
        select{
        case <-t.C:
            fmt.Printf("ticker: run\n")
        }
    }
}(ticker)

goroutine周期性執(zhí)行一些事務時非常有用,比如狀態(tài)狀態(tài)日志弦疮、輸出夹攒、計算等。

例如:

ticker := time.NewTicker(time.Second * 3)
defer ticker.Stop()

fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
time.Sleep(time.Second * 4)

for{
    select{
    case <-ticker.C:
        fmt.Println(time.Now())
    }
}

time.NewTicker

NewTicker方法用于返回一個新的Ticker胁塞,Ticker中包含一個通道字段C會每隔時間段d就向該通道發(fā)送當前的時間咏尝。

func time.NewTicker(d time.Duration) *time.Ticker
  • 時間間隔d的單位為納秒(ns, int64)压语,在工廠函數(shù)time.NewTicker中以time.Duration類型的參數(shù)傳入。
  • *Ticker指向定時器的指針

例如:定時執(zhí)行编检,循環(huán)執(zhí)行不退出胎食。

//創(chuàng)建計時器,每隔1秒后定時器會向channel發(fā)送一個事件蒙谓,包含當前時間斥季。
ticker := time.NewTicker(time.Second * 1)

i:=0
for{
    //執(zhí)行若干次后退出
    if i>5 {
        break
    }
    i++

    fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
    //從打點器中獲取通道
    <-ticker.C
}

//清理計時器
ticker.Stop()

例如:

//創(chuàng)建計時器训桶,每隔1秒后定時器會向channel發(fā)送一個事件累驮,包含當前時間。
ticker := time.NewTicker(time.Second * 1)

i:=0
for{
    //執(zhí)行若干次后退出
    if i>5 {
        //清理計時器
        ticker.Stop()
        //跳出循環(huán)
        break
    }
    //從打點器中獲取通道
    select{
    case <-ticker.C:
        i++
        fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
    }
}

例如:

ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for{
    select{
    case t := <-ticker.C:
        fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
    }
}

time.Tick

time.Tick()返回的是一個通道舵揭,每隔指定時間就會有數(shù)據(jù)從通道中出來谤专。

 func Tick(d Duration) <-chan Time {
    if d <= 0 {
        return nil
    }
    return NewTicker(d).C
}

實現(xiàn)固定時間重復執(zhí)行,即定期循環(huán)午绳。

for{
    time.Sleep(time.Second * 2)
    fmt.Println(time.Now())
}

更優(yōu)雅的方案

  • range是可以不接收遍歷的值的置侍,若不接收則可簡寫。
for range time.Tick(time.Second * 2){
    fmt.Println(time.Now())
}

ticker.Stop

func (t *Ticker) Stop() {
    stopTimer(&t.r)
}
  • ticker.Stop()方法會關閉一個Ticker拦焚,關閉后將不會再發(fā)送更多的tick信息蜡坊。
  • ticker.Stop()方法不會關閉通道t.C,只能避免從通道的讀取不正確的成功赎败。

ticker.Reset

func (t *Ticker) Reset(d Duration) {
    if t.r.f == nil {
        panic("time: Reset called on uninitialized Ticker")
    }
    modTimer(&t.r, when(d), int64(d), t.r.f, t.r.arg, t.r.seq)
}

時間段

time.Duration

  • time.Durationtime包定義的一個類型秕衙,表示一段時間間隔。
  • Duration類型表示兩個時間點之間經(jīng)過的時間段僵刮,以納秒為單位据忘,可表示的最長時間段大約290年。
  • Duration時間段實際上是int64類型搞糕,單位納秒勇吊。

實際編程中不會直接賦值時間段為一個數(shù)字,而是會采用time包提供的常量窍仰。

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

時間運算

Add

  • 獲取時間點增加時間段后的時間點
func (t Time) Add(d Duration) Time

例如:計算1天后的時間點

t1 := time.Now()
fmt.Println(t1)//2021-04-18 18:27:30.482194 +0800 CST m=+0.002020201

t2 := t1.Add(time.Hour * 24)
fmt.Println(t2)//2021-04-19 18:27:30.482194 +0800 CST m=+86400.002020201

例如:計算1天前的時間點

t2 := t1.Add(-time.Hour * 24)
fmt.Println(t2)//2021-04-17 18:30:48.1375322 +0800 CST m=-86399.998035299

Sub

  • 計算兩個事件之間的差值
func (t Time) Sub(u Time) Duration

例如:

t1 := time.Now()
fmt.Println(t1)//2021-04-18 18:27:30.482194 +0800 CST m=+0.002020201

t2 := t1.Add(time.Hour * 24)
fmt.Println(t2)//2021-04-17 18:30:48.1375322 +0800 CST m=-86399.998035299

d := t2.Sub(t1)
fmt.Println(d)//24h0m0s

時間比較

Equal

func (t Time) Equal(u Time) bool
  • 判斷兩個時間點tu是否相同汉规,會考慮時區(qū)的影響。

例如:

t1 := time.Now()
fmt.Println(t1)//2021-04-18 18:27:30.482194 +0800 CST m=+0.002020201

t2 := t1.Add(time.Hour * 24)
fmt.Println(t2)//2021-04-17 18:30:48.1375322 +0800 CST m=-86399.998035299

flag := t2.Equal(t1)
fmt.Println(flag)//false

Before

func (t Time) Before(u Time) bool
  • 判斷時間點t是否在指定時間點u之前

After

func (t Time) After(u Time) bool
  • 判斷某時間點t是否在指定時間點u之后
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驹吮,一起剝皮案震驚了整個濱河市针史,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钥屈,老刑警劉巖悟民,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異篷就,居然都是意外死亡射亏,警方通過查閱死者的電腦和手機近忙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來智润,“玉大人及舍,你說我怎么就攤上這事】弑粒” “怎么了锯玛?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長兼蜈。 經(jīng)常有香客問我攘残,道長,這世上最難降的妖魔是什么为狸? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任歼郭,我火速辦了婚禮,結果婚禮上辐棒,老公的妹妹穿的比我還像新娘病曾。我一直安慰自己,他們只是感情好漾根,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布泰涂。 她就那樣靜靜地躺著,像睡著了一般辐怕。 火紅的嫁衣襯著肌膚如雪逼蒙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天秘蛇,我揣著相機與錄音其做,去河邊找鬼。 笑死赁还,一個胖子當著我的面吹牛妖泄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艘策,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蹈胡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了朋蔫?” 一聲冷哼從身側響起罚渐,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驯妄,沒想到半個月后荷并,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡青扔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年源织,在試婚紗的時候發(fā)現(xiàn)自己被綠了翩伪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡谈息,死狀恐怖缘屹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侠仇,我是刑警寧澤轻姿,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站逻炊,受9級特大地震影響互亮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗅骄,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一胳挎、第九天 我趴在偏房一處隱蔽的房頂上張望饼疙。 院中可真熱鬧溺森,春花似錦、人聲如沸窑眯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磅甩。三九已至炊林,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卷要,已是汗流浹背渣聚。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僧叉,地道東北人奕枝。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像瓶堕,于是被迫代替她去往敵國和親隘道。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 類型 time.Time{} 時間類型,包含了秒和納秒以及Location time.Month() type M...
    吃貓的魚0閱讀 31,757評論 0 4
  • golang使用的版本: go version go1.10.3 一:功能介紹 time的一些功能郎笆,比如時區(qū)谭梗,像l...
    九卷技術錄閱讀 534評論 0 1
  • Go time Go中提供了很多關于時間處理的內(nèi)容,這篇文章來主講講解下時間上的內(nèi)容宛蚓。 最外層可以直接使用的方法 ...
    qingshuiting閱讀 919評論 0 1
  • time 包的官方文檔 中文英文本文章不是對time包文檔的重復激捏,旨在加深對time實現(xiàn)的理解上,以上是文檔可以進...
    _AlphaBaby_閱讀 673評論 0 0
  • 原文鏈接 http://ironxu.com/747 介紹Go 標準庫 time 常用導出函數(shù)凄吏,結構體及其方法远舅。 ...
    好剛編程閱讀 16,958評論 2 11