ホームページ  >  記事  >  バックエンド開発  >  タイムパッケージの単調クロック処理

タイムパッケージの単調クロック処理

Golang菜鸟
Golang菜鸟転載
2023-08-04 17:45:081283ブラウズ

今日は主に golang time パッケージの時刻適用方法を見ていきます。

コンピュータのクロック処理には、主に 2 つの方法があります:

  • 壁掛け時計 (実時間)
  • 単調時計

この 2 つの間の一般的なルールは、「経過時間」は 時間を伝えるために使用されますが、「単調時計」は 測定に使用されます。 time; さらに、他のクロック処理方法もあります。

上記の 2 つの時計の概念がまだ理解できない場合は、次のページにアクセスすることをお勧めします。

コンピュータの時間を本当に理解していますか? [1]この記事では、これら 2 つの時計の起源について詳しく説明します。

以下を読む前に、

Wall ClockMonotone Clock が何であるかをすでに知っていることを前提とします。

次に、

time.Time (機械翻訳) の概要を見ていきます。

Time は、ナノ秒の精度で時刻を表します。

時間を使用するプログラムは、通常、時間をポインタではなく値として保存し、渡す必要があります。つまり、時間変数と構造体フィールドの型は *time.Time ではなく、time.Time である必要があります。

時間値は、GobDecode、UnmarshalBinary、を除く複数のゴルーチンで同時に使用できます。 UnmarshalJSON メソッドと UnmarshalText メソッドは同時実行安全ではありません。

時刻は、Before、After、Equal メソッドを使用して比較できます。 Sub メソッドは 2 つの瞬間を減算して継続時間を生成します。 Add メソッドは、時間に期間を加算して時間を生成します。

Time 型のゼロ値は、1 年 1 月 1 日、00:00:00.000000000 UTC です。この時間が実際には発生する可能性は低いため、IsZero メソッドは、明示的に初期化されていない時間を検出する簡単な方法を提供します。

各時間は場所に関連付けられており、時間の表現を計算するときに参照されます。 たとえば、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 は利用可能な最も正確な比較を使用し、1 つのパラメーターのみが単調クロック読み取り値を持つ場合を正しく処理するためです。

これは time.TIME の公式紹介です。 Time の構造がどのようなものかを見てみましょう:

type Time struct {
 wall uint64
 ext  int64

 loc *Location
}

wall その最上位ビットには 1 ビットのフラグが含まれています。 hasMonotonic を表し、その後に秒を追跡する 33 ビットが続き、最後に範囲 [0, 999999999] のナノ秒を追跡する 30 ビットが続きます。

hasMonotonic ビットが 0 の場合、33 ビット フィールドは 0 で、ext には 2020 年 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) 時間 {...}
  • func Unix(sec int64, nsec int64) 時間 {...}
  • func UnixMilli(sec int64, nsec int64) 時間 {...}
  • func UnixMicro(sec int64, nsec int64) Time {...}
  • func (t Time) AddDate(year int, months int, days int) Time { ...}

これらの概念と知識を読んだ後、時間パッケージの使用に習熟していただけることを願っています。

以上がタイムパッケージの単調クロック処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はGolang菜鸟で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。