27

2007 年に、サマータイムに切り替える日が変わりました。その変更より前の DST の拡張範囲内にある日付は、Chrome と Firefox で誤ったタイムゾーン オフセットを報告しています。Firefox と Chrome は、以前は DST の曜日が異なっていたという事実に注意を払っていないようです。

次のスクリプトを実行すると、240 分のオフセットが報告されます。それは正しくありません。300 分と報告されるはずです。IE10 はこれを正しく行います。誰も修正を知っていますか?

alert(new Date('11/04/2004').getTimezoneOffset());

アップデート:

これは、私が一緒にハッキングした興味深いコードです (以下を参照)。IE 以外のすべてのブラウザーで、ほとんどの日付がどれだけずれているかは本当に驚くべきことです。開始日と終了日をこれと比較してください: http://www.timeanddate.com/worldclock/timezone.html?n=77&syear=2000

getTimezoneOffset の Date のプロトタイプを、ハードコーディングされたテーブルに基づいて計算する独自のプロトタイプに置き換えるだけになりました。私たちは米国でしかビジネスを行っていないので、それは私たちにとってはうまくいきます.それは私が想像できる最悪の解決策についてです.

<!DOCTYPE html>
<html>
    <head>
        <title>Moment Test</title>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.0.0/moment.min.js"></script>
        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
        <script>
var lastOffset = null;
var $tbody = null;
var endDate = new Date('01/01/2021');

function addDate(d) {
    if($tbody === null)
        $tbody = $('#dates');

    var offset = d.getTimezoneOffset();
    var s = '';
    if(lastOffset != offset) {
        if(lastOffset != null)
            s = '<tr style="background-color: red;">';
        lastOffset = offset;
    }
    else {
        s = '<tr>';
    }
    var m = new moment(d);
    s += '<td>' + m.format('YYYY-MM-DD') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ssZ') + '</td><td>' + m.format('YYYY-MM-DDTHH:mm:ss') + '</td><td>' + offset + '</td></tr>';
    $tbody.append($(s));
    d.setDate(d.getDate() + 1);

    if(d < endDate)
        window.setTimeout(function(){addDate(d)}, 0);
}

        </script>
    </head>
    <body>
        <button onclick="addDate(new Date('01/01/1980'));">Fill Table</button>
        <table border="1">
            <thead><tr><th>Date</th><th>Date 2</th><th>Date 3</th><th>TZ Offset</th></tr></thead>
            <tbody id='dates'></tbody>
        </table>
    </body>
</html>
4

2 に答える 2

35

実際には、現在の DST 規則を使用し、調査対象の特定の日時に設定されている規則を無視するという動作が指定されています。ES5 15.9.1.8を参照してください。

「ECMAScript の実装では、正確な時刻が夏時間の対象であったかどうかを判断しようとするのではなく、現在の夏時間アルゴリズムがその時点で使用されていた場合に夏時間が有効になっていたかどうかを判断しようとする必要があります。これにより、次のような複雑さが回避されます。ロケールが 1 年を通してサマータイムを実施した年を考慮に入れたものです。」

ルールは次のとおりです。現在の DST ルールを、指定された時間に適用します。これは無意味な動作をもたらしますが、ECMAScript が必要とするものです。

この動作は ECMAScript の将来のバージョンで変更され、すべての時点で実際の DST ルールを使用する必要が生じる可能性があります。これは、実装者に課せられる tzdata の出荷の負担のため、最初は必要ありませんでした。しかし、言語は十分に重要になっているため、長期的にはおそらく誰もがそれを吸収しなければならないでしょう. しかし、変化は私が知る限り何年も先になる可能性があるので、息を止めないでください.

于 2013-06-05T23:23:08.330 に答える
4

これが JavaScript の真のバグであることを確認しました。

  • 夏時間に従う一般的な米国のタイムゾーンでテスト済み
    • 東部、中部、山岳、太平洋
  • Chrome、Firefox、Safari でテストされ、失敗しました (最新バージョン)
  • IE 6、7、8、9 でテストされ、失敗しました。
  • IE 10 でテストされ、合格しました (影響はありません)。
  • Windows 7、8、および Mac OSX でテスト済み。

これはかなり厄介です。誰かが根本的な原因を知っていますか?

WebKitのバグかと思いましたが、FirefoxはGeckoを使用しています。

さまざまな問題リストを確認しましたが、この特定の問題はどこにも見つかりませんでした。おそらく私は何かを逃した。複数の場所に影響するため、どこにバグ レポートを提出すればよいかわかりません。

おそらくそれはコア JavaScript バグでしょうか? この基本的なことが単体テストで見落とされているとは本当に信じがたいです。

OS が TZDB ではなく Windows タイムゾーンを使用しているため、おそらく Windows システムに影響しているだけだと思いましたが、Mac でも発生するため、そうではないようです。

JavaScript の日付が厄介であることは誰もが知っていますが、少なくともこれに依存できると思いました。オフセットを調べたり、解析を行う必要さえありません。次の値を確認してください。

new Date(2004,10,4)  // recall, js months are 0-11, so this is Nov. 4 2004.

2004 年、米国では 10 月 31 日の午前 2 時に夏時間が終了し、時計は午前 1 時に戻りました。したがって、11 月 4 日までにはすべて標準時になるはずですが、そうではありません。たとえば、コンソールの Chrome 開発ツールで、時計を米国東部時間帯に設定すると、次のようになります。

> new Date(2004,10,7,0,0)
  Sun Nov 07 2004 00:00:00 GMT-0400 (Eastern Daylight Time)

> new Date(2004,10,7,1,0)
  Sun Nov 07 2004 01:00:00 GMT-0500 (Eastern Standard Time)

11月7日に移行日を設定しています。これは、現在有効な「11 月の第 1 日曜日」ルールに続くものですが、2004 年には「10 月の最後の日曜日」の古いルールになるはずでした。

更新 1

ブラウザに限定して表示されるものではありません。 Node.jsでも失敗します

Node.js スクリーンショット

IE が問題ないことを証明するために、IE10 からの出力を次に示します。

IE10 スクリーンショット

興味深いことに、IE と Firefox は 1:00 のあいまいさを夏時間として解決し、Chrome はそれを標準時間として解決しますが、それは別の問題です。正しい移行日を選択します。

更新 2

最新の Firefox 21 ではこの問題が発生しますが、正しいオフセットが使用されているにもかかわらず、標準名の昼光を切り替える別の問題によって複雑になるため、別の方法で表示されます。つまり、Firefox では、出力は次のようになります。

Firefox のスクリーンショット

于 2013-06-05T19:58:28.513 に答える