20

タイムゾーン オフセット (分単位) があり、そのタイムゾーンを決定する必要があるシナリオがあります。すべてのデータが利用できないことはわかっていますが (たとえば、オフセットが -240 分のタイムゾーンがいくつかある可能性があります)、「最良の推測」は受け入れられます。

私の最初のパスは次のようになりました。

foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
    if (info.BaseUtcOffset.TotalMinutes == timezoneOffset)
    {
         // do something here if this is a valid timezone
    }
}

これはある程度機能しますが、夏時間を考慮に入れる必要があるため、多少気が遠くなります。この恐ろしいハックを追加しました:

foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
    var extra = info.IsDaylightSavingTime(DateTime.Now) ? 60 : 0;
    if (info.BaseUtcOffset.TotalMinutes + extra == timezoneOffset)
    {
         // do something here if this is a valid timezone
    }
}

これは、夏時間が有効でないときにユーザーに正確な時刻を表示できるという点で「十分に」機能し、DST 中は約 70% 正確です。それでも...これは私の目にはひどいコードです。

これを行うより良い方法はありますか?優雅さが増せば良く、精度が高ければさらに良いでしょう。

アップデート

技術的には、Javascript が日付に関して取得できるあらゆる情報にアクセスできます。「オフセット」と呼ばれる隠しフィールドを配置したページがあります。オフセット フィールドに DateTime().getTimezoneOffset() を入力する JQuery 関数があります。DateTime オブジェクトに役立つものは何も見当たりませんが、おそらくこれにより、他のアイデアへの道が開かれるでしょう。

4

2 に答える 2

21

簡単な答え: できません。

サマータイムはそれを不可能にします。たとえば、夏季のアリゾナとカリフォルニアの違い、または冬のアリゾナとニューメキシコの違いを UTC オフセットだけから判断する方法はありません (アリゾナは DST を観察しないため)。

また、さまざまな国が DST をいつ遵守するかという問題もあります。たとえば、米国の DST は、ヨーロッパよりも早く開始し、遅く終了します。

正確な推測は可能ですが (例: +/- 1 時間)、ユーザーに時間を表示するためにそれを使用している場合、一部のユーザーに間違った時間を表示することは避けられません。


更新: コメントから、主な目標はユーザーのローカル タイムゾーンでタイムスタンプを表示することのようです。それがあなたのやりたいことなら、時間を UTC タイムスタンプとして送信し、Javascript を使用してユーザーのブラウザーでそれを書き換えるだけです。Javascript が有効になっていない場合でも、使用可能な UTC タイムスタンプが表示されます。これは、この質問で思いついた関数で、この Greasemonkey スクリプトで使用しました。ニーズに合わせて微調整することもできます。

//@param timestamp An ISO-8601 timestamp in the form YYYY-MM-DDTHH:MM:SS±HH:MM
//Note: Some other valid ISO-8601 timestamps are not accepted by this function
function parseISO8601(timestamp)
{
  var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$");
  var matches = regex.exec(timestamp);
  if(matches != null)
  {
    var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
    if(matches[7] == "-")
      offset = -offset;

    return new Date(
      Date.UTC(
        parseInt(matches[1], 10),
        parseInt(matches[2], 10) - 1,
        parseInt(matches[3], 10),
        parseInt(matches[4], 10),
        parseInt(matches[5], 10),
        parseInt(matches[6], 10)
      ) - offset*60*1000
    );
  }
  return null;
}

これは、ユーザーのローカル タイムゾーンで解析されたタイムスタンプを表示するためにブログで使用する関数です。繰り返しますが、必要な形式に微調整できます。

var weekDays = new Array("Sunday", "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday");
var months = new Array("January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December");

function toLocalTime(date)
{
  var hour = date.getHours();
  var ampm = (hour < 12 ? "am" : "pm");
  hour = (hour + 11)%12 + 1;

  var minutes = date.getMinutes();
  if(minutes < 10)
    minutes = "0" + minutes;

  return weekDays[date.getDay()] + ", "
       + months[date.getMonth()] + " "
       + date.getDate()          + ", "
       + date.getFullYear()      + " at "
       + hour                    + ":"
       + minutes                 + " "
       + ampm;
}
于 2009-08-13T21:37:26.047 に答える
5

DST のため、UTC からのオフセットだけでは、自分がどのタイムゾーンにいるのかわかりません。DST がその時点で有効であったかどうかを推測するために時間の一部を調べることを検討することもできますが、さまざまな管轄区域で DST の定義が変更されるため、政治的な考慮事項により、それはほぼ不可能になります。

于 2009-08-13T21:41:53.803 に答える