2012-09-01 16 views
5

私の要件はかなり標準です。ユーザーが自分の現在のTimeZoneを選択して自分のアカウントに対して保存できるようにする必要があります。次に、この値を使用して、保存されたDateTimeの値をローカライズされた時刻に変換します。ユーザーのタイムゾーン設定を保存する

私の現在の考え方は、私は、ユーザーが(もっとやすい説明ができるようにDBで開催されたが、TimeZoneInfo.GetSystemTimeZones()を使用して構築)リストから.NET TimeZoneInfo.Idを選択することができるようになるということである - 私は、関連するTimeZoneInfoインスタンスを返すために、この値を使用しますTimeZoneInfo.FindSystemTimeZoneById()を使用して変換を実行します。私がここで見る主な問題は、TimeZoneInfo.Idがレジストリに保持されている値であり、 "標準" Idではないことです(例えばOlsonと比較して)。したがって、サーバーの更新/移行によって、格納されたIDが完全に無効になり、変換が中断される可能性があります。

簡潔に言えば、このアプローチは有効/そうでない場合は、ユーザのタイムゾーン設定を保存し、昼間の節約などを追加のロジックなしで処理するより良い方法がありますか?

+0

['DateTimeOffset'](http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx)を見ましたか?または['NodaTime'](http://code.google.com/p/noda-time/)? – Oded

+0

関連:http://stackoverflow.com/q/2532729/1583 – Oded

+1

@Oded DateTimeOffsetの問題は、Day Light Savings対応ではないことです。 – Paparazzi

答えて

8

私はこの古いish未回答の質問を見つけたので、私はそれを刺すべきだと思った。

簡潔に言えば、このアプローチは有効/安全ですか?

すべては、あなたがそれらをどのように計画しているかによって異なります。

サーバー側のコードでのみ使用している場合は、はい。単にタイムゾーンのIdを保存し、ユーザーに対応するDisplayNameを表示するだけです。 FindSystemTimeZoneByIdGetSystemTimeZonesはこれに対して完全に有効です。

Idの値は常に同じですが、DisplayNameのプロパティは、コードを実行しているWindowsオペレーティングシステムの言語によって異なります。実装はであり、では認識されないため、.NETで異なるターゲットカルチャを設定するだけでDisplayName文字列は変更されません。

Microsoft Windowsのタイムゾーンデータベースのレコードはかなり安定しており、Windows Update経由で更新されます。 の情報の一部はレジストリから取得されますが、ローカライズされたリソース文字列はtzres.dllから取得されています。もちろん、そのすべてはTimeZoneInfoとそれに関連するクラスによって隠されています。

ただし、これらのタイムゾーンIdの値を他のシステムに渡す場合は注意してください。以前のバージョンのWindowsではいくつかのバリエーションがあります。たとえば、私は表示名がすべて "GMT"と言い、現在はより正確に "UTC"と言われていることを知っています。 Idの値は同じですが、それ以外のものが一貫していないことを正確に知っています。特に、ターゲットコンピュータがあなたが持っている同じWindows Updateセットを受信して​​いない場合。ちなみに、更新は、hereと発表されています。

また、Windowsタイムゾーンデータベースに関するいくつかのことを知っている必要があります。

  • これは、暦年ごとに二つ以上のDST遷移を表すことができません。たとえば、 - in 2010, Cairo, Egypt had four transitionsとなります。 Microsoftはa hotfixを発行しましたが、これは妥協的な修正を行ったに過ぎず、歴史的に正確なものではありませんでした。このような歴史的な変化があり、正しく表現できないゾーンが他にもあります。

  • Windows XP/2003とVista/2008の間でいくつかの変更がありました。このhereについての本当に良い情報がいくつかあり、レジストリの使用方法についての詳細があります。

  • マイクロソフトは独自のタイムゾーンデータベースを持つメジャープレーヤーです。他の国ではIANA/Olson databaseが使用されています。これは、相互運用性の問題につながります。私はthe timezone tag wikiにこれについてまともな書面を書いています。

またTimeZoneInfoが密接DateTimeDateTimeOffsetクラスにリンクされていることを知っている必要があります。これらには独自のセットがあります。 DateTimeOffsetはやや使えますが、DateTimeはニュアンスが詰まっています。読む:

.NETでの日付と時刻にはるかよりよい解決策はNodaTimeを使用することです。このライブラリは、のタイムゾーンデータベースとその間のCLDRマッピングを実装しています。また、より安全なAPIを提供し、問題に陥ることもありません。再学習するには少し時間がかかるかもしれませんが、それを知る前に、LocalDateTimeZonedDateTimeOffsetDateTimeInstantのようなクラスを使用します。

タイムゾーンデータベースを頻繁に更新するという問題はありますが、私たちは政治家に計時ルールを任せています。しかし、the TZDB folksは、データベースを歴史的に正確に保ち、​​ゾーン名が変わるとエイリアス/リンクを提供するのには大変良い仕事です。あなたはtzの名前hereのリストを見ることができます。

また、NodaTimeをお持ちの場合は、配布物にコンパイルされたTZDBのコピーを貼り付けるか、自分のアプリケーションと共に配布することができます。あなたは(理論的に)IANAから最新のバージョンをプルダウンして、アプリケーションを更新したままにするためのコードを書くことができます。すべて、ホストのオペレーティングシステムに依存しません。

+0

timezoneinfo.IDの全体の意味は理解できません。 IDは、いくつかのISO標準の方法に従う識別子であると予想されます。しかし、私はちょうど 'FindSystemTimeZoneById'が異なるバージョンのWindows間で正しく動作しないことを知りました。あるバージョンでは、返される文字列はすべて小文字であり、もう1つはラクダ文字であり、問​​題を悪化させるためにFindSystemTimeZoneByIdは大文字と小文字を区別しません。 Go figure! – Rajiv

+0

@Rajiv - タイムゾーンのISO標準はありません。 IANA/Olsonの識別子(前述)は標準に最も近いものです。 WindowsのIDに関して、私は小文字であるものに遭遇したことはありません。上記のように、あるシステムにインストールされていて、別のシステムにはインストールされていない新しく導入されたタイムゾーンについて話していない限り、IDはシステム全体で一貫している必要があります。たとえば、[KB3093504](https://support.microsoft.com/en-us/kb/3093503)では、修正プログラムに「北朝鮮標準時」が導入されました。 –

関連する問題