本日は.NETの小ネタ枠です。
DateTimeOffset型をDateTime型に変換する方法についてです。
DateTime型とDateTimeOffset型
DateTime型は特定の時刻と世界協定時刻(UTC)またはローカル(Local)かの種別情報を保持します。
一方でDateTimeOffset型は特定のUTC時刻とタイムゾーンのオフセットを保持します。
learn.microsoft.com
learn.microsoft.com
DateTime型からDateTimeOffset型への変換
DateTimeOffsetコンストラクタまたは暗黙的な変換が可能です。
本変換ではDateTime型の種別に応じた適切なUTC時刻とオフセットがDateTimeOffsetに引き継がれます。
DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15, System.DateTimeKind.Local); DateTimeOffset dateOffset1 = new DateTimeOffset(date1);
または
DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15, System.DateTimeKind.Local); DateTimeOffset dateOffset1 = date1;
DateTimeOffset型からDateTime型への変換
DateTimeOffset.DateTimeプロパティが利用できますが、UTCかLocalかの種別情報が失われる点に注意が必要です。
変換後のDateTime型に種別情報を設定するにはDateTimeOffset.UtcDateTimeプロパティまたはDateTimeOffset.LocalDateTimeプロパティを利用します。
以下はDateTimeOffset型が保持しているオフセットからUTC時刻、Local時刻、それ以外を判定して変換を行う一例です。
DateTime ConvertFromDateTimeOffset(DateTimeOffset dateTime) { if (dateTime.Offset.Equals(TimeSpan.Zero)) return dateTime.UtcDateTime; else if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime))) return DateTime.SpecifyKind(dateTime.DateTime, DateTimeKind.Local); else return dateTime.DateTime; }
サンプルスクリプト
以下のDateTime型からDateTimeOffset型の変換と逆変換を行い、ログ出力するサンプルスクリプトを作成して結果を確認してみました。
void Main() { // 1. Local時刻とUTC時刻のDateTimeを作成 System.DateTime date1 = new System.DateTime(2010, 1, 1, 8, 0, 15, System.DateTimeKind.Local); System.DateTime date2 = new System.DateTime(2010, 1, 1, 8, 0, 15, System.DateTimeKind.Utc); Debug.Log($"date1: {date1}, Kind: {date1.Kind}"); Debug.Log($"date2: {date2}, Kind: {date2.Kind}"); // 2. DateTime型をDateTimeOffset型に変換 System.DateTimeOffset dateOffset1 = new System.DateTimeOffset(date1); System.DateTimeOffset dateOffset2 = new System.DateTimeOffset(date2); Debug.Log($"dateOffset1: {dateOffset1}"); Debug.Log($"dateOffset2: {dateOffset2}"); // 3. DateTimeOffset型をDateTime型に変換 // DateTimeOffset.DateTimeプロパティを利用した場合、KindプロパティがUnspecifiedになり情報が失われる System.DateTime date3 = dateOffset1.DateTime; System.DateTime date4 = dateOffset2.DateTime; Debug.Log($"date3: {date3}, Kind: {date3.Kind}"); Debug.Log($"date4: {date4}, Kind: {date4.Kind}"); // 4. DateTimeOffset.UtcDateTimeまたはDateTimeOffset.LocalDateTimeプロパティを利用してKindプロパティを保持して変換する // 以下の処理ではDateTimeOffset.OffsetプロパティがTimeSpan.Zeroの場合はUTC時刻、 // ローカル時刻のオフセットが一致すればLocal時刻、それ以外の場合はUnspecifiedとして変換している System.DateTime date5 = ConvertFromDateTimeOffset(dateOffset1); System.DateTime date6 = ConvertFromDateTimeOffset(dateOffset2); Debug.Log($"date5: {date5}, Kind: {date5.Kind}"); Debug.Log($"date6: {date6}, Kind: {date6.Kind}"); } DateTime ConvertFromDateTimeOffset(DateTimeOffset dateTime) { if (dateTime.Offset.Equals(TimeSpan.Zero)) return dateTime.UtcDateTime; else if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime))) return DateTime.SpecifyKind(dateTime.DateTime, DateTimeKind.Local); else return dateTime.DateTime; }
出力結果は以下の通りです。
date1: 2010/01/01 8:00:15, Kind: Local date2: 2010/01/01 8:00:15, Kind: Utc dateOffset1: 2010/01/01 8:00:15 +09:00 dateOffset2: 2010/01/01 8:00:15 +00:00 date3: 2010/01/01 8:00:15, Kind: Unspecified date4: 2010/01/01 8:00:15, Kind: Unspecified date5: 2010/01/01 8:00:15, Kind: Local date6: 2010/01/01 8:00:15, Kind: Utc