.NET で日時を扱うとき、「UTC(協定世界時)」に変換することは非常に重要です。特に Web API や分散システムを開発する場合、ローカルタイムでの管理はトラブルの元になります。この記事では、DateTime を UTC に変換する方法と、意外と知られていない注意点について解説します。
DateTime を UTC に変換する基本方法
.NET では、DateTime.ToUniversalTime() メソッドを使うことで、ローカル日時から UTC に変換することができます。
DateTime localTime = DateTime.Now;
DateTime utcTime = localTime.ToUniversalTime();
Console.WriteLine($"UTC: {utcTime}");
このコードでは、現在のローカル時刻を UTC に変換して出力します。
注意点1: DateTime.Kind の意味
DateTime 構造体には Kind プロパティがあり、これが変換時の挙動に影響します。
- DateTimeKind.Local: ローカル時間として解釈される
- DateTimeKind.Utc: すでに UTC 時間として扱われる
- DateTimeKind.Unspecified: タイムゾーンが指定されていない
例:Unspecified の落とし穴
DateTime dt = new DateTime(2024, 1, 1, 10, 0, 0, DateTimeKind.Unspecified);
DateTime utc = dt.ToUniversalTime();
Console.WriteLine(utc); // 予期せぬ時間になる可能性あり!
Unspecified の場合、システムは「現在のローカルタイムゾーン」を仮定して変換してしまいます。明示的に Kind を指定することが重要です。
注意点2: DateTimeOffset との違い
DateTime はタイムゾーン情報を保持しません。一方、DateTimeOffset はオフセット(+09:00 など)を保持しており、UTC に変換しやすくなっています。
DateTimeOffset dto = DateTimeOffset.Now;
DateTimeOffset utcOffset = dto.ToUniversalTime();
Console.WriteLine(utcOffset); // 正確な UTC 時間
注意点3: クライアントとサーバー間でのズレ
Web アプリケーションでは、クライアント側(JavaScript など)とサーバー側(C#)でタイムゾーンの扱いが異なることに注意が必要です。
例えば、クライアントから送られてきた日時が ISO 8601 形式(例:2024-01-01T10:00:00)の場合、Kind は Unspecified になります。そのため、受信時に UTC として扱う場合は、適切に変換する処理を加える必要があります。
DateTime parsed = DateTime.SpecifyKind(DateTime.Parse("2024-01-01T10:00:00"), DateTimeKind.Utc);
まとめ
- ToUniversalTime()を使うことでローカル時刻を UTC に変換できる
- DateTime.Kindを適切に設定しないと誤変換のリスクがある
- より安全に日時を扱いたい場合はDateTimeOffsetを使う
- クライアントとのやり取りでは、文字列の形式とKindの扱いに注意
UTC を正しく扱うことは、グローバル対応やバグの防止に繋がります。日付時刻の取り扱いは一見地味ですが、システムの信頼性に大きく関わるので、ぜひ丁寧に設計しましょう。