首頁  >  文章  >  後端開發  >  time包的單調時鐘處理

time包的單調時鐘處理

Golang菜鸟
Golang菜鸟轉載
2023-08-04 17:45:081279瀏覽

我們今天主要是來看看golang time 套件的時間應用方式。

在說到電腦處理時鐘上,主要的分為2種方式:

  • 在牆上時鐘(wall time)
  • #單調時鐘(monotonic clocks)

兩者的一般規則是「wall time」用於告知時間,而「monotonic clock」用於測量時間;除外還有其他的時鐘處理方式。

如果你還不了解上面兩種時鐘的概念,那麼我推薦你可以先訪問:你真的了解電腦的時間嗎? [1]這篇文章詳細說明了這兩種時鐘的來歷。

在看下面的內容之前,我會認為你已經知道了什麼是 牆上時鐘單調時鐘

我接下來看一段 time.Time 的介紹(透過機器翻譯而來):

Time 表示具有奈秒精度的時間瞬間。

使用時間的程式通常應該將它們作為值而不是指標來儲存和傳遞。也就是說,時間變數和結構欄位的類型應該是 time.Time,而不是 *time.Time。

一個 Time 值可以同時被多個 goroutine 使用,除了 GobDecode、UnmarshalBinary、 UnmarshalJSON 和 UnmarshalText 方法不是並發安全的。

可以使用 Before、After 和 Equal 方法來比較時間瞬間。 Sub 方法減去兩個瞬間,產生一個持續時間。 Add 方法為一個時間增加一個持續時間,產生一個時間。

Time 類型的零值是 1 月 1 日,第 1 年,00:00:00.000000000 UTC。由於這個時間在實務上不太可能出現,因此 IsZero 方法提供了一種簡單的方法來偵測尚未明確初始化的時間。

每個 Time 都與一個 Location 相關聯,在計算時間的表示形式時會參考它, 例如在 Format、Hour 和 Year 方法中。 Local、UTC 和 In 方法傳回具有特定位置的時間。以這種方式更改位置只會更改簡報;它不會改變表示的時刻,因此不會影響前面段落中描述的計算。

GobEncode、MarshalBinary、MarshalJSON 和 MarshalText 方法儲存的時間值表示儲存 Time.Location 的偏移量,但不儲存位置名稱。因此,他們會失去有關夏令時的資訊。

除了所需的「掛鐘」讀數外,時間還可以包含當前進程單調時鐘的可選讀數,以提供額外的比較或減法精度。有關詳細信息,請參閱套件文件中的“單調時鐘”部分。

請注意,Go == 運算子不僅比較時間瞬間,還比較位置和單調時鐘讀取。因此,在沒有先保證已為所有值設定相同位置的情況下,不應將時間值用作地圖或資料庫鍵,這可以透過使用UTC 或本地方法來實現,並且單調時鐘讀數已被剝離設定t = t.Round(0)。一般來說,比起 t == u,偏好 t.Equal(u),因為 t.Equal 使用最準確的比較可用並且正​​確處理只有一個參數具有單調時脈讀數的情況。

到這裡官方提供的 time.TIme 的介紹已經說完了。讓我們一起來看看 Time 的結構是什麼樣的:

type Time struct {
 wall uint64
 ext  int64

 loc *Location
}

wall 它的最高位元包含一個1位元標誌。表示hasMonotonic,然後是33位元用來追蹤秒數;最後是30位,用於追蹤奈秒,範圍為[0,999999999]。

如果該hasMonotonic位元為0,則33位元欄位為零,而ext 儲存自1年1月1日以來的完整帶符號的64位元wall秒數。

如果该hasMonotonic位为1,则33位字段存储自1885年1月1日以来的无符号的wall秒数,而ext保留有符号的64位单调时钟读数,距离进程开始的时间为纳秒。这是大多数代码中通常发生的情况。

我们来通过 time.now() 函数来查看其中的区别:

// Now returns the current local time.
func Now() Time {
 sec, nsec, mono := now() // 返回对应的秒数,纳秒数,单调时钟数
 mono -= startNano
 sec += unixToInternal - minWall
 if uint64(sec)>>33 != 0 { // 判断如果秒数右移33位后大于0,说明不能采用单调时钟。
  return Time{uint64(nsec), sec + minWall, Local} // 按照 `wall` 时钟返回
 }
  
  // 返回 `wall` 时钟和 `monotonic` 时钟信息
 return Time{hasMonotonic | uint64(sec)<<nsecShift | uint64(nsec), mono, Local}
}

通过这个例子我们可以看到在time包中对于时间差的计算基本都会采用单调时钟墙上时钟的兼容。

  • func (t Time) After(u Time) bool {...}
  • func (t Time) Before(u Time) bool {...}
  • func (t Time) Equal(u Time) bool {...}
  • func (t Time) Add(d Duration) Time {...}
  • func (t Time) Sub(u Time) Duration {...}
  • func Since(t Time) Duration {...}
  • func Until(t Time) Duration {...}

对于增加修改时间计算会清除单调时钟,因为后面调用的是 unixTime 函数:

func unixTime(sec int64, nsec int32) Time {
 return Time{uint64(nsec), sec + unixToInternal, Local}
}

不会计算单调时钟的秒数,如下:

  • func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {...}
  • #func Unix(sec int64, nsec int64) Time {...}
  • #func UnixMilli(sec int64, nsec int64) Time {...}
  • #func UnixMicro(sec int64, nsec int64) Time {...}
  • func (t Time) AddDate(years int, months int, days int) Time { ...}

希望看完這些概念和知識對你使用time包的時間更加的熟練。

#

以上是time包的單調時鐘處理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Golang菜鸟。如有侵權,請聯絡admin@php.cn刪除