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