2013-06-07 10 views
8

「DateTime」の値を別のタイムゾーンからUTCに、またはその逆に変換する必要があります。私はTimeZoneInfoを使ってこれを行います。しかし、この問題は、「Day Light Saving」の時間の変化が起こるときです。どうやって 'あいまいな時間'に対処しますか?

たとえば、今度は11月3日に2AM [CDT]で次回の時刻変更が行われます.11AM 3日には1AM [CDT]が6AMに変換され、次の1時間に時間が変わると[現在はCST]となり、6AMに変換されます。私はthisページのコードを試しましたが、この問題をどのように処理するかは言いませんでした。だからこの問題に対処するには???

編集:

私はNodaTimeを試してみましたが、私は

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

のような変換を行うときには、AmbiguousTimeExceptionをスローします。 Thats goodと私はTimeZoneInfoを使ってもこれを行うことができます。しかし、私はどのlocalTime値を選ぶ必要があるかをどのように知っていますか?

編集2:ここ

はマットとのチャット議論のためのlinkです。

+3

Noda Timeは、このようなシナリオに役立つように特別に設計されています。 – SLaks

答えて

9

あなたが持っているのは現地時間であり、その時間があいまいである場合、を正確なUTCインスタントに変換できません。そういうわけで、私たちは "あいまい"と言います。

たとえば、IANAゾーン名がAmerica/Chicagoで、WindowsゾーンIDがCentral Standard Timeである米国中部標準時ゾーンでは、「中央標準時」と「中央夏時間」の両方をカバーしています。私が知っていることは、2013年11月3日午前1時に、この時間があいまいであり、これが中央夏時間にあった午前1時の最初のインスタンスかどうかを知る方法は全くありません(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)を使用することを選択しました。 (1AMに6時間を追加すると7AMになります)。時間があいまいだったという警告は皆さんにはありませんでした。あなたこのように、自分自身をチェックしている可能性:

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を使用する場合は、あいまいさが避けられません。

+0

ありがとうございます。しかし、問題はあなたがオフセットをどのように決定するのか?私は正しいオフセットを決定することを意味する、あなたは夏時間の節約にあるかどうかを知る必要があります。それが私の問題です! – usp

+0

できません。あなたはそれを記録する必要があります。たとえば、イベント中に 'DateTimeOffset.Now'を使用します。または、入力として入力することもできます。オフセットがない場合、あいまいさを解決することはできません。 –

+0

標準のオフセットはありますが、夏時間オフセットはありません。だから両方のオフセット値を保存することをお勧めしますか? – usp