標準のDateTime
形式からUTCへの変換はどのように機能しますか?
より具体的には、あるタイムゾーンでDateTime
オブジェクトを作成し、別のタイムゾーンに切り替えてその上でToUniversalTime()
を実行すると、変換が正しく行われ、その時間まだ正確に表現されていますか?
DateTime
オブジェクトにアタッチされる暗黙的なタイムゾーンはありません。 ToUniversalTime()
を実行すると、コードが実行されているコンテキストのタイムゾーンが使用されます。
たとえば、1970年1月1日のエポックからDateTime
を作成すると、世界のどこにいても同じDateTime
オブジェクトが得られます。
グリニッジでコードを実行しているときにToUniversalTime()
を実行すると、同じ時間になります。バンクーバーに住んでいる間にそれを行うと、-8時間のオフセットDateTime
オブジェクトを取得します。
これが、何らかの種類の日付変換またはローカライズを行う必要がある場合、時間関連情報をデータベースにUTC時間として保存することが重要な理由です。コードベースが別のタイムゾーンのサーバー施設に移動したかどうかを検討してください;)
編集:ジョエルの答えからのメモ-DateTime
オブジェクトはデフォルトで_DateTimeKind.Local
_と入力されます。日付を解析し、_DateTimeKind.Utc
_として設定した場合、ToUniversalTime()
は変換を実行しません。
そして、ここに "Date Timesによるコーディングのベストプラクティス" に関する記事と、 。NetによるDateTimesの変換 に関する記事があります。
まず、Kind
のDateTime
がすでにUTCであることがわかっているかどうかを確認します。その場合、同じ値を返します。
それ以外の場合は、ローカル時間と見なされます-実行しているコンピューターのローカル時間、特に、プライベートプロパティが最初に遅延初期化されたときにコンピューターが使用していたタイムゾーンのローカル時間です。つまり、タイムゾーンを変更した場合afterアプリケーションが開始された場合、まだ古いものを使用している可能性が十分にあります。
タイムゾーンには、現地時間をUTC時間に、またはその逆に変換するのに十分な情報が含まれていますが、あいまいまたは無効な時間があります。 (現地時間は2回発生し、現地時間は夏時間のために発生することはありません。)これらのケースを処理するためのルールは ドキュメント で指定されています:
日付と時刻のインスタンス値があいまいな時間である場合、このメソッドはそれが標準時間であると想定します。 (あいまいな時間は、ローカルタイムゾーンの標準時間または夏時間にマップできる時間です)日付と時刻のインスタンス値が無効な時間である場合、このメソッドはローカルタイムゾーンのローカル時間を単純に減算しますUTCを返すUTCオフセット。 (無効な時間とは、夏時間調整規則の適用のために存在しない時間です。)
返される値のKind
はDateTimeKind.Utc
。したがって、ToUniveralTime
を呼び出すと、オフセットは再び適用されません。 (これは.NET 1.1と比べて大幅に改善されています!)
非ローカルタイムゾーンが必要な場合は、.NET 3.5で導入された TimeZoneInfo
を使用する必要があります(以前のバージョンにはハッキーなソリューションがありますが、ニースではありません)。インスタントを表すには、 DateTimeOffset
の使用を検討する必要があります。これは、.NET 2.0SP1、.NET3.0SP1、および.NET 3.5で導入されました。ただし、それに関連付けられている実際のタイムゾーンはまだありません。UTCからのオフセットだけです。つまり、たとえば現地時間は1時間後になるのか分からないということです。DSTルールは、特定の瞬間に同じオフセットを使用したタイムゾーン間で異なる場合があります。 TimeZoneInfo
は、やや単純な TimeZone
とは対照的に、歴史的および将来のルールを考慮するように設計されています。
基本的に、.NET 3.5のサポートは以前よりもはるかに優れていますが、適切なカレンダー演算に必要なものが残っています。誰でも空想的な移植 Joda Time .NETに? ;)
@ womp発言 、さらにDateTimeのKindプロパティをチェックして、alreadyがUTC日付であるかどうかを確認します。
DateTime.ToUniversalTimeは、ローカルタイムゾーンのタイムゾーンオフセットを削除して、DateTimeをUTCに正規化します。その後、別のタイムゾーンの正規化された値でDateTime.ToLocalTimeを使用すると、そのタイムゾーンでの正しい表現のために、そのタイムゾーンのタイムゾーンオフセットが正規化された値に追加されます。