現地時間しかなく、その時間が曖昧な場合、正確な UTC インスタントに変換することはできません。それが「あいまい」と言う理由です。
たとえば、米国中部タイム ゾーンでは、IANA ゾーン名America/Chicago
と Windows ゾーン ID がありCentral Standard Time
、「中央標準時」と「中央夏時間」の両方をカバーします。2013 年 11 月 3 日の午前 1:00 であることがわかっている場合、この時刻はあいまいであり、これが中央夏時間の午前 1:00 の最初のインスタンスであったかどうかを知る方法はまったくありません。 (UTC-5)、または中部標準時 (UTC-6)。
プラットフォームが異なれば、あいまいな時刻を UTC に変換するように求められたときの動作も異なります。通常は夏時間である最初のインスタンスを使用するものもあります。通常は 2 番目のインスタンスである標準時を使用するものもあります。例外をスローするものもあれば、(NodaTime のように) 何を実行するかを選択できるものもあります。
まずは始めましょうTimeZoneInfo
。
// Despite the name, this zone covers both CST and CDT.
var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var dt = new DateTime(2013, 11, 3, 1, 0, 0);
var utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
Debug.WriteLine(utc); // 11/3/2013 7:00:00 AM
ご覧のとおり、.net は「標準」時刻である UTC-6 を使用することを選択しました。(午前 1 時に 6 時間を追加すると午前 7 時になります)。時間が曖昧であるという警告はありませんでした。次のように、自分自身をチェックできます。
if (tz.IsAmbiguousTime(dt))
{
throw new Exception("Ambiguous Time!");
}
しかし、これを強制するものは何もありません。自分で確認する必要があります。
あいまいさをなくす唯一の方法は、型を使用しないことです。DateTime
代わりに、 を使用できますDateTimeOffset
。観察:
// Central Standard Time
var dto = new DateTimeOffset(2013, 11, 3, 1, 0, 0, TimeSpan.FromHours(-6));
var utc = dto.ToUniversalTime();
Debug.WriteLine(utc); // 11/3/2013 7:00:00 AM +00:00
// Central Daylight Time
var dto = new DateTimeOffset(2013, 11, 3, 1, 0, 0, TimeSpan.FromHours(-5));
var utc = dto.ToUniversalTime();
Debug.WriteLine(utc); // 11/3/2013 6:00:00 AM +00:00
次に、これを NodaTime と比較します。
var tz = DateTimeZoneProviders.Tzdb["America/Chicago"];
var ldt = new LocalDateTime(2013, 11, 3, 1, 0, 0);
// will throw an exception, only because the value is ambiguous.
var zdt = tz.AtStrictly(ldt);
// will pick the standard time, like TimeZoneInfo did
var zdt = tz.AtLeniently(ldt);
// manually specify the offset for CST
var zdt = new ZonedDateTime(ldt, tz, Offset.FromHours(-6));
// manually specify the offset for CDT
var zdt = new ZonedDateTime(ldt, tz, Offset.FromHours(-5));
// with any of the above, once you have a ZonedDateTime
// you can get an instant which represents UTC
var instant = zdt.ToInstant();
ご覧のとおり、多くのオプションがあります。すべて有効です。それは、あなたが何をしたいかによって異なります。
あいまいさを完全に回避したい場合は、常に を保持するDateTimeOffset
か、NodaTime を使用する場合はZonedDateTime
またはを使用しOffsetDateTime
ます。DateTime
またはを使用する場合LocalDateTime
、あいまいさを避けることはできません。