1. ホーム
  2. c#

[解決済み] DateTimeとDateTimeOffsetの比較

2022-03-19 21:56:49

質問

とはどのような違いがあるのでしょうか? DateTimeDateTimeOffset また、どのような場合にどちらを使うべきでしょうか?


現在、.NETの標準的な対応方法である DateTime をTimeZoneを意識した形で実装しています。を生成するときは常に DateTime はUTCで行います(例えば DateTime.UtcNow を表示するたびに、UTCからユーザーのローカルタイムに変換しています。

これで問題なく動作していますが、私は DateTimeOffset と、オブジェクト自体にローカルとUTCの時刻をキャプチャする方法です。

解決方法は?

DateTimeOffset の表現です。 瞬時の時間 (としても知られています)。 絶対時間 ). つまり、誰にとっても普遍的な時間の瞬間(を考慮しない)を意味するのです。 うるう秒 の相対論的な効果もあります。 タイムディレイ ). 瞬間的な時間を表現するもう1つの方法は DateTime ここで .KindDateTimeKind.Utc .

とは区別されます。 カレンダー時間 (として知られている)。 市民時間 というのは、誰かのカレンダー上の位置であり、世界中にはさまざまなカレンダーが存在します。 私たちはこれらのカレンダーを タイムゾーン . カレンダーの時刻は DateTime ここで .KindDateTimeKind.Unspecified または DateTimeKind.Local . そして .Local は、結果を使用するコンピュータがどこに配置されているかが暗黙の了解になっているシナリオでのみ意味を持ちます。 (たとえば、ユーザーのワークステーションなど)

では、なぜ DateTimeOffset の代わりに、UTCの DateTime ? 遠近感が大事なんです。 例えて言うなら、写真家のフリをしてみましょう。

カレンダータイムラインの上に立ち、目の前に広がる瞬間的なタイムライン上の人物にカメラを向けていると想像してください。 タイムゾーンの規則に従ってカメラを構えます。タイムゾーンはサマータイムやタイムゾーンの法的な定義が変更されることによって定期的に変わります。 (手元が定まらないので、カメラは手ぶれします)。

写真に立つ人は、あなたのカメラが来た角度を見ることになります。他の人が撮っていれば、違うアングルからの写真になる可能性もあります。これが Offset の部分は DateTimeOffset を表します。

カメラに「東部時間」というラベルを貼った場合、-5から指しているときもあれば、-4から指しているときもあります。 中には隣同士(あるいは上同士)のカメラもあり、オフセットを知るだけでは、どのタイムゾーンに関連した時間なのかを判断することはできないのです。

そして、UTCはどうでしょうか? まあ、手ブレがないことが保証されているのは、そこそこのカメラですからね。 三脚の上で地面にしっかりと固定されている。どこにも行きません。 私たちはこの角度をゼロオフセットと呼んでいます。

では、この例えが何を物語るのか。 直感的なガイドラインを提供します。

  • ある特定の場所からの相対的な時間を表現する場合、カレンダータイムで表現するために DateTime . ただ、あるカレンダーと他のカレンダーを決して混同しないように注意してください。 Unspecified が前提であるべきです。 Local から来る場合のみ有効です。 DateTime.Now . 例えば、次のような場合です。 DateTime.Now で、それをデータベースに保存します - しかし、私がそれを取り出すとき、それは Unspecified . ローカルのカレンダーが、元々そのカレンダーから取得したものと同じであるかどうかは、信頼できないのです。

  • 常に瞬間を確かめなければならない場合は、瞬間的な時間を表現していることを確認します。 使用方法 DateTimeOffset を使用して強制するか、UTC DateTime を慣習的に使用する。

  • もし、瞬時の時間を追跡する必要があるが、「ユーザーがローカルのカレンダーで何時だと思ったか」も知りたい場合は、次のようにします。 を使う DateTimeOffset . これは、例えば、時間管理システムにおいて、技術的および法的な懸念の両方から、非常に重要なことです。

  • 以前に記録したものを修正する必要がある場合 DateTimeOffset - オフセットだけでは、新しいオフセットがユーザーにとってまだ適切であることを確認するのに十分な情報がありません。 そのため また タイムゾーン識別子を格納します(位置が変わっても新しい写真を撮れるように、そのカメラの名前が必要だと考えてください)。

    また、以下の点も指摘しておきます。 野田時間 という表現があります。 ZonedDateTime が、.Netの基底クラスライブラリには同様のものがない。 の両方を保存する必要があります。 DateTimeOffsetTimeZoneInfo.Id の値を指定します。

  • 時には、それを見ている人のローカルなカレンダー時刻を表現したい場合があります。 例えば 今日 を意味します。 今日は常に午前0時から午前0時までですが、これらは瞬時のタイムライン上では無限に近い数の重なり合う範囲を表します。 (実際にはタイムゾーンの数は有限ですが、刻み目までのオフセットを表現することができます)したがって、このような状況では、「誰が聞いているのか」という質問を単一のタイムゾーンに限定するか、適宜、瞬時の時間に変換して対処する方法を理解しておく必要があります。

について、その他の小ネタを紹介します。 DateTimeOffset この例えの裏付けと、それを維持するためのヒントがあります。

  • 2つを比較すると DateTimeOffset の値は、比較する前にまずオフセットがゼロになるように正規化されます。 言い換えれば 2012-01-01T00:00:00+00:002012-01-01T02:00:00+02:00 は、同じ瞬間的な瞬間を指すので、等価である。

  • ユニットテストを行っていて、オフセットを確認する必要がある場合は、テスト 両方 DateTimeOffset の値、および .Offset プロパティを個別に指定します。

  • .Netフレームワークには一方向の暗黙の変換機能が組み込まれており、この機能により DateTime を任意の DateTimeOffset パラメータや変数があります。 その際 .Kind 事項 . UTC の種類を渡すと、オフセットが 0 になって持ち込まれます。 .Local または .Unspecified であると仮定します。 ローカル . フレームワークは基本的に、「カレンダーの時間を瞬時に変換するように言われたけど、これがどこから来たのかわからないから、ローカルのカレンダーを使うことにするよ」と言っているのです。 DateTime をタイムゾーンの異なるコンピュータで使用することができます。 (IMHO - 例外を投げるべきですが、投じません)。

シェイムレス・プラグ

多くの人がこの例えを非常に貴重だと言ってくれたので、私のPluralsightコースに取り入れました。 日付と時刻の基礎 . カメラの例えを段階的に説明したものは、2番目のモジュール「Context Matters"」の「Calendar Time vs. Instantaneous Time」というクリップで見ることができます。