web-dev-qa-db-ja.com

ASP.NETでタイムゾーンを使用する方法

「オンラインアラームシステム」プロジェクトに取り組んでいます(ASP.NET 2.0(C#)/ SQL Server 2005)

これは、特定の日にユーザーにメールを送信するリマインダーサービスであるためです。しかし、問題は、ユーザーが特定の国の出身ではなく、世界中のさまざまなタイムゾーンの出身であるということです。今、私が登録するとき、私はウィンドウがインストール時に私たちのタイムゾーンを尋ねるのと同じ方法でユーザーのタイムゾーンを求めています。

しかし、ユーザーが(+5.30)またはタイムゾーンを選択した場合、asp.netアプリケーションでこのタイムゾーンを処理する方法はわかりません。タイムゾーンに従って作業する方法。

そして、このアプリケーションでタイムゾーンを処理するより良い方法があるかどうかを提案してください??

ありがとう

27
Prashant

まず、データがどのタイムゾーンにあるかを確認します。保存するDateTimeはすべてUTC時間で保存することをお勧めします(DateTime.ToUniversalTime()を使用して保持することをお勧めします)。

ユーザーにリマインダーを保存する場合、現在のUTC時間を必要とし、ユーザーのタイムゾーンの差を追加または削除し、その新しい時間をUTCに変換します。これは、DBに保存するものです。

次に、送信するリマインダーを確認する場合は、データベースを調べて、UTC時間に従ってリマインダーを送信する必要があります。基本的に、DateTime.Now.ToUniversalTime()の前にあるタイムスタンプを持つすべてのアラームを取得します。

更新いくつかの実装仕様:タイムゾーンのリストはTimeZoneInfo.GetSystemTimeZones()メソッドから取得できます。これらを使用して、ユーザーのタイムゾーンのリストを表示できます。選択したタイムゾーンからIdプロパティを保存する場合、そこからTimeZoneInfoクラスインスタンスを作成し、特定のローカル日付/時刻値のUTC時間を計算できます。

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("<the time zone id>");
// May 7, 08:04:00
DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0);
DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset);
27
Fredrik Mörk

私は常にサーバー側でUTC(GMT)時間を使用し(コードビハインド、データベースなどで)、UTCから表示目的の現地時間のみ。つまり、データベースでの時間の節約、計算の実行など、すべての時間操作はUTCを使用して実行する必要があります。

問題は、コードビハインドがクライアントブラウザーのタイムゾーンをどのように認識しているかということです。ユーザーがフォームに何らかの日付/時刻の値(12/30/2009 14:30など)を入力し、サーバーに送信するとします。ユーザーが現地時間を送信したと仮定すると、サーバーはこの値をUTCに変換する方法をどのように知っていますか?

アプリケーションは、ユーザーにタイムゾーンの指定(および永続的なCookieまたはデータベースへの保存)を求めることができますが、ユーザーの追加の労力が必要であり、アプリはこのためのロジックと画面を実装する必要があります。アプリがクライアントのタイムゾーンを自動的に決定できる方が良いでしょう。

JavaScriptの getTimezoneOffset 関数を使用してこの問題に対処しました。これは、クライアントのローカル時間とGMTの時差をサーバーに通知できる唯一のAPIです。これはクライアント側のAPIであるため、次のことを行いました。サーバー側で、タイムオフセット値を保持するカスタムセッションCookieを確認し、使用できない場合はページをリロードします(POSTではなくGET呼び出し中のみ)タイムオフセットを生成してCookieに保存するJavaScriptロジックが追加されています。クライアント側からは、これはほとんど透過的です(セッション中に一度GETでページをリロードします)。 Cookieにオフセットを設定したら、時間変換の方向(UTCから現地時間、または現地時間からUTC)に応じて時間管理機能に適用します。

これは少し複雑に聞こえるかもしれませんが、ヘルパー関数を作成した後、この機能をサイトに統合することは、単一呼び出しを行うことでした Page_Load(時間変換が必要なページの)で、およびブラウザーとの間で時間値を送受信するときに時間変換ルーチンを使用します。使用方法の例を次に示します。

using My.Utilities.Web;
...

// Derive the form class from BaseForm instead of Page.
public class WebForm1: BaseForm
{
...
private void Page_Load(object sender, System.EventArgs e)
{
  // If we only want to load the page to generate the time
  // zone offset cookie, we do not need to do anything else.
  if (InitializeLocalTime())
    return;

  // Assume that txtStartDate is a TextBox control.
  if (!IsPostback)
  {
     // To display a date-time value, convert it from GMT (UTC)
     // to local time.
     DateTime startDate = GetStartDateFromDB(...);
     txtStartDate.Text  = FormatLocalDate(startDate);
     ...
  }
  else
  {
     // To save a date-time value, convert it from local
     // time to GMT (UTC).
     DateTime tempDate  = DateTime.Parse(txtStartDate.Text);
     DateTime startDate = ConvertLocalTimeToUtc(tempDate);
     SaveStartDateInDB(startDate, ...);
     ...
  }
}
...
}

より詳細な情報が必要な場合は、 時間について:ASP.NETアプリケーションでの時間のローカライズ の記事をご覧ください(申し訳ありませんが、asp以来、出版社のサイトの記事への直接リンクはありません。 netPROは有料購読者のみにアクセスを制限します; PDFコピー)へのリンクがあります。記事からサンプルを投稿できればいいのですが、著作権を侵害したくありません; 、ここに ヘルパーライブラリをビルドするプロジェクト があり、これには必要なすべての機能とドキュメントがあります(しないものは無視してください)必要)。

更新:この記事は、新しい出版社 here によってサンプルプロジェクトとともにオンラインで投稿されました。

17
Alek Davis

これまでのすべての答えの問題は、Prashantが達成しようとしていることを考慮していないことです。夏時間の変更の前日にシステムのユーザーが+12のオフセットを持ち、翌日のリマインダーを設定した場合、リマインダーがトリガーされるはずのユーザーのオフセットは+13になります。

そのため、現在発生していることに対してのみ現在のオフセットを使用できます。私は他のすべての人に同意しますが、サーバー側(表示のみに使用される可能性があるものを除く)は常にUTCで保存する必要があります。

3
Paul

フレームワーク2.0以降を使用している場合は、DateTimeの代わりに DateTimeOffset 構造の使用を検討してください。

DateTimeOffsetは、UTC時間を基準とした特定の時点を表すため、この場合は作業しやすいはずです。

2
Rune Grimstad

2つのステップがあります。

  • Javascriptを使用してクライアント側で異なるタイムゾーンを検出します。

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • 次に、サーバー側で、上記の検出されたタイムゾーンオフセットに基づいてサーバー時間をクライアント時間に変換するC#コード:

------------------------;

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}
1
Minh Nguyen

問題は、UTCからのオフセットが1年の異なる時期に異なることです。各タイムゾーンには独自のルールがあります。 (会議室のスケジュールアプリを開発するとき、これは難しい方法でした。)

ここに組み込みのサポートがあるように見えます: http://msdn.Microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

自分で試したことはありませんが、夏時間を考慮した正しい変換を約束しているようです。

そうでない場合、ここに私が使用した(価格の高い)商用ツールがあります。 http://www.worldtimeserver.com/time_zone_guide/

0
Matt Sherman

基本的に、ユーザーが入力した現地時間にオフセット(時間+分)を追加するだけです。オフセットを追加すると、基本的にUTC(基本的にはGMT)タイムゾーンのDateTimeが得られます。

通常、すべての時間をUTCに標準化するのが最も簡単です。これにより、アプリケーションロジックがオフセットを処理する必要がなくなります。

このページにはいくつかの良い例があります: http://msdn.Microsoft.com/en-us/library/bb546099.aspx

0
Andy White