927

DateTimeaとaの違いは何DateTimeOffsetですか?いつ使用する必要がありますか?


DateTime現在、 TimeZone対応の方法で.NETを処理する標準的な方法がありますDateTime。UTCで作成する場合は常に(たとえば、を使用してDateTime.UtcNow)、表示する場合は常にUTCからユーザーの現地時間に変換し直します。 。

DateTimeOffsetこれは問題なく機能しますが、オブジェクト自体でローカル時間とUTC時間をキャプチャする方法について読んでいます。

4

10 に答える 10

1477

DateTimeOffset瞬間時間(絶対時間とも呼ばれます)の表現です。つまり、すべての人にとって普遍的な瞬間を意味します(うるう秒、または時間の遅れの相対論的効果を考慮していません)。瞬間時間を表す別の方法は、whereisを使用するDateTimeこと.KindですDateTimeKind.Utc

これは、誰かのカレンダー上の位置であるカレンダー時間(常用時とも呼ばれます)とは異なり、世界中にさまざまなカレンダーがあります。これらのカレンダーをタイムゾーンと呼びます。カレンダーの時間は、、またはDateTimeで表されます。そして、結果を使用しているコンピューターがどこに配置されているかを暗黙的に理解しているシナリオでのみ意味があります。(たとえば、ユーザーのワークステーション).KindDateTimeKind.UnspecifiedDateTimeKind.Local.Local

では、なぜDateTimeOffsetUTCの代わりにDateTimeそれはすべて視点についてです。 例えを使ってみましょう-私たちは写真家のふりをします。

あなたがカレンダーのタイムラインに立って、目の前に配置された瞬間的なタイムライン上の人物にカメラを向けていると想像してください。タイムゾーンのルールに従ってカメラを並べます。これは、夏時間のため、またはタイムゾーンの法的な定義に対するその他の変更のために定期的に変更されます。(手が安定していないため、カメラが不安定です。)

写真に立っている人は、あなたのカメラがどこから来たのかを見るでしょう。他の人が写真を撮っている場合、彼らは異なる角度からである可能性があります。これは、のOffset一部がDateTimeOffset表すものです。

したがって、カメラに「東部標準時」というラベルを付けると、-5から指している場合もあれば、-4から指している場合もあります。世界中にカメラがあり、すべて異なるものにラベルが付けられており、すべてが異なる角度から同じ瞬間のタイムラインを指しています。それらのいくつかは互いに隣接している(または上にある)ため、オフセットを知っているだけでは、時間がどのタイムゾーンに関連しているかを判断するのに十分ではありません。

そしてUTCはどうですか?まあ、それは安定した手を持っていることが保証されているそこにある唯一のカメラです。三脚の上にあり、地面にしっかりと固定されています。それはどこにも行きません。その遠近法をゼロオフセットと呼びます。

瞬時時間とカレンダー時間の視覚化

それで、このアナロジーは私たちに何を伝えますか?それはいくつかの直感的なガイドラインを提供します-

  • 特にある場所に関連する時間を表す場合は、カレンダー時間で。を使用して表しDateTimeます。あるカレンダーを別のカレンダーと混同しないように注意してください。 Unspecifiedあなたの仮定でなければなりません。 Localから来るだけで便利ですDateTime.Now。たとえば、取得DateTime.Nowしてデータベースに保存する場合がありますが、取得するときは、であると想定する必要がありUnspecifiedます。私のローカルカレンダーが元々取得されたものと同じであるとは信じられません。

  • 常に瞬間を確認する必要がある場合は、瞬間的な時間を表していることを確認してください。DateTimeOffsetそれを強制するために使用するかDateTime、慣例によりUTCを使用します。

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

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

    また、 Noda Timeにはこれを必要とする表現がありZonedDateTimeますが、.Net基本クラスライブラリには同様のものがないことも指摘しておく必要があります。DateTimeOffsetaと値の両方を保存する必要がありTimeZoneInfo.Idます。

  • 場合によっては、「それを見ている人」にローカルなカレンダー時間を表現したい場合があります。たとえば、今日の意味を定義するとき。今日は常に真夜中から真夜中ですが、これらは瞬間的なタイムライン上でほぼ無限の数の重複する範囲を表しています。(実際には、タイムゾーンの数には限りがありますが、目盛りまでのオフセットを表現できます)したがって、このような状況では、「誰が質問しているのか」を制限する方法を理解してください。単一のタイムゾーンに質問するか、必要に応じてそれらを瞬間的な時間に戻すことに対処します。

これは、このアナロジーを裏付ける他のいくつかのちょっとしたDateTimeOffsetことと、それをまっすぐに保つためのいくつかのヒントです。

  • 2つの値を比較する場合、比較DateTimeOffsetする前に、最初にゼロオフセットに正規化されます。言い換えれば、2012-01-01T00:00:00+00:002012-01-01T02:00:00+02:00は同じ瞬間の瞬間を指し、したがって同等です。

  • 単体テストを実行していて、オフセットを確認する必要がある場合は、値とプロパティの両方を個別にテストしてください。DateTimeOffset.Offset

  • DateTime.Net Frameworkには、任意のDateTimeOffsetパラメーターまたは変数にを渡すことができる一方向の暗黙的な変換が組み込まれています。そうするとき.Kind問題。UTCの種類を渡すと、オフセットはゼロになりますが、またはのいずれかを渡す.Localと、ローカル.Unspecifiedであると見なされます。フレームワークは基本的に、「カレンダーの時刻を瞬間的な時刻に変換するように言われましたが、これがどこから来たのかわからないので、ローカルカレンダーを使用します」と言っています。異なるタイムゾーンのコンピュータに不特定のものをロードする場合、これは大きな落とし穴です。(IMHO-例外をスローする必要があります-しかし、そうではありません。)DateTime

恥知らずなプラグ:

多くの人がこのアナロジーは非常に価値があると私と共有しているので、私はそれを私のPluralsightコースのDate andTimeFundamentalsに含めました。2番目のモジュール「ContextMatters」の「CalendarTimevs.Instantaneous Time」というタイトルのクリップで、カメラのアナロジーのステップバイステップのウォークスルーを見つけることができます。

于 2013-01-10T22:09:06.603 に答える
448

Microsoftから:

DateTimeOffset値のこれらの使用法は、DateTime値の使用法よりもはるかに一般的です。結果として、DateTimeOffsetは、アプリケーション開発のデフォルトの日付と時刻のタイプと見なす必要があります。

出典:「DateTime、DateTimeOffset、TimeSpan、TimeZoneInfoのいずれかを選択する」MSDN

DateTimeOffsetアプリケーションが特定の時点(レコードが作成/更新されたときなど)を処理するため、ほぼすべてに使用します。ちなみに、SQLServer2008でも使用DATETIMEOFFSETしています。

DateTime日付のみ、時間のみ、または一般的な意味でのいずれかを処理する場合に役立つと思います。たとえば、毎日午前7時に鳴りたいアラームがある場合、DSTに関係なく、午前7時に鳴りたいので、をDateTime利用してそれを保存できます。ただし、アラーム発生の履歴を表す場合は、を使用します。DateTimeKindUnspecifiedDateTimeOffset

タイプを組み合わせて使用​​する場合DateTimeOffsetDateTime特にタイプを割り当てて比較する場合は注意が必要です。また、比較時にタイムゾーンオフセットが無視されるためDateTime、同じインスタンスのみを比較してください。DateTimeKindDateTime

于 2013-01-09T19:42:01.917 に答える
103

DateTimeは、現地時間とUTCの2つの異なる時刻のみを保存できます。Kindプロパティはどちらかを示します。

DateTimeOffsetは、世界中のどこからでも現地時間を保存できるようにすることで、これを拡張します。また、その現地時間とUTCの間のオフセットも保存されます。そのUTCオフセットを保存するためにクラスにメンバーを追加しない限り、DateTimeがこれを実行できないことに注意してください。または、UTCでのみ機能します。それ自体は素晴らしいアイデアです。

于 2010-12-02T17:47:08.860 に答える
35

DateTimeOffset理にかなっている場所がいくつかあります。1つは、定期的なイベントと夏時間の処理を行う場合です。毎日午前9時にアラームを鳴らすように設定したいとします。「UTCとして保存、現地時間として表示」ルールを使用すると、夏時間が有効になっている別の時間にアラームが鳴ります。

おそらく他にもありますが、上記の例は実際には過去に遭遇したものです(これはDateTimeOffset、BCLに追加する前でした-当時の私の解決策は、ローカルタイムゾーンに時間を明示的に保存し、保存することでしたそれに沿ったタイムゾーン情報:基本的にDateTimeOffset内部で何をするか)。

于 2010-12-02T02:59:58.997 に答える
32

最も重要な違いは、DateTimeはタイムゾーン情報を保存しませんが、DateTimeOffsetは保存することです。

DateTimeはUTCとLocalを区別しますが、それに関連付けられた明示的なタイムゾーンオフセットはまったくありません。何らかのシリアル化または変換を行う場合は、サーバーのタイムゾーンが使用されます。UTC時間をオフセットするために分を追加して手動で現地時間を作成した場合でも、(DateTimeに明示的なオフセットがないため)サーバーのタイムゾーンオフセットを使用するため、シリアル化ステップでビットを取得できます。

たとえば、Json.NetとISO日付形式を使用してKind = LocalでDateTime値をシリアル化すると、のような文字列が得られます2015-08-05T07:00:00-04。最後の部分(-04)は、DateTimeまたはそれを計算するために使用したオフセットとは関係がないことに注意してください...これは、純粋にサーバーのタイムゾーンオフセットです。

一方、DateTimeOffsetには明示的にオフセットが含まれます。タイムゾーンの名前が含まれていない場合もありますが、少なくともオフセットが含まれています。シリアル化すると、サーバーの現地時間が何であれ、値に明示的に含まれているオフセットが取得されます。

于 2015-08-05T23:00:02.093 に答える
30

Microsoftのこのコードは、すべてを説明しています。

// Find difference between Date.Now and Date.UtcNow
  date1 = DateTime.Now;
  date2 = DateTime.UtcNow;
  difference = date1 - date2;
  Console.WriteLine("{0} - {1} = {2}", date1, date2, difference);

  // Find difference between Now and UtcNow using DateTimeOffset
  dateOffset1 = DateTimeOffset.Now;
  dateOffset2 = DateTimeOffset.UtcNow;
  difference = dateOffset1 - dateOffset2;
  Console.WriteLine("{0} - {1} = {2}", 
                    dateOffset1, dateOffset2, difference);
  // If run in the Pacific Standard time zone on 4/2/2007, the example
  // displays the following output to the console:
  //    4/2/2007 7:23:57 PM - 4/3/2007 2:23:57 AM = -07:00:00
  //    4/2/2007 7:23:57 PM -07:00 - 4/3/2007 2:23:57 AM +00:00 = 00:00:00
于 2018-10-19T09:32:00.947 に答える
13

これらすべての素晴らしい答えを読みたくない場合はTLDR :-)

明示的

DateTimeOffsetタイムゾーンがUTC+0に強制されるために使用します。

暗黙的

誰もが常にUTC+0であるタイムゾーンの不文律に固執することを望むDateTime場所を使用します。


(開発者向けの補足:明示的は暗黙的よりも常に優れています!)

(Java開発者向けのサイドノート、C#DateTimeOffset== Java OffsetDateTime、これを読んでください:https ://www.baeldung.com/java-zoneddatetime-offsetdatetime )

于 2020-08-18T13:28:55.927 に答える
8

主な違いは、現在のタイムゾーン以外のタイムゾーンで現地時間に変換するためDateTimeOffsetにと組み合わせて使用​​できることです。TimeZoneInfo

これは、さまざまなタイムゾーンのユーザーがアクセスするサーバーアプリケーション(ASP.NETなど)で役立ちます。

于 2010-12-02T13:03:40.060 に答える
3

私が見るDateTimeOffsetの唯一のマイナス面は、MicrosoftがXmlSerializerクラスでそれをサポートすることを(設計上)「忘れた」ことです。しかし、それ以降、XmlConvertユーティリティクラスに追加されました。

XmlConvert.ToDateTimeOffset

XmlConvert.ToString

すべての利点があるため、先に進んでDateTimeOffsetとTimeZoneInfoを使用すると言います。XMLとの間でシリアル化される、またはシリアル化される可能性のあるエンティティ(すべてのビジネスオブジェクト)を作成するときは注意してください。

于 2014-04-09T11:11:41.753 に答える
0

DateTime.Now
金03Dec21 18:40:11

DateTimeOffset.Now
金03Dec21 18:40:11 +02:00

したがって、DateTimeOffset時刻がUTCとどのように関連しているか、基本的にはタイムゾーンに関する情報を格納します。

于 2021-12-03T17:41:48.280 に答える