10

「DateTime」値を異なるタイムゾーンから UTC に、またはその逆に変換する必要があります。これには TimeZoneInfo を使用します。しかし、問題は「サマータイム」の時間変更がいつ発生するかです。

たとえば、今年は、次回は 11 月 3 日の午前 2 時 [CDT] に時刻が変更されます。したがって、11 月 3 日の午前 1 時 [CDT] は午前 6 時に変換され、次の時間に時刻が変更されると、午前 1 時 [現在の CST] になります。再び午前 6 時に変換されます。このページのコードを試してみましたが、この問題の処理方法については何も書かれていませんでした。では、この問題をどのように処理するのですか?

編集:

NodaTimeを試してみましたが、次のような変換を行うと

 DateTimeZoneProviders.Tzdb["America/Chicago"].AtStrictly(<localDateTime>) 

AmbiguousTimeException をスローします。それは良いことです。TimeZoneInfo を使用してこれを行うこともできます。しかし、どの localTime 値を選択する必要があるかを知るにはどうすればよいでしょうか?

編集2:

Matt とのチャット ディスカッションへのリンクは次のとおりです。

4

1 に答える 1

11

現地時間しかなく、その時間が曖昧な場合、正確な 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、あいまいさを避けることはできません。

于 2013-06-08T00:03:08.410 に答える