なぜこれら 2 つのエポック ミリ タイム (1927 年) を減算すると奇妙な結果になるのでしょうか? 質問する

なぜこれら 2 つのエポック ミリ タイム (1927 年) を減算すると奇妙な結果になるのでしょうか? 質問する

1 秒間隔で時間を参照する 2 つの日付文字列を解析して比較する次のプログラムを実行すると、

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

出力は次のようになります。

353

なぜld4-ld3、 ではなく1(時間の 1 秒の差から予想されるように) なのでしょうか353?

日付を1秒後の時刻に変更すると、次のようになります。

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

それではld4-ld3になります1


Javaバージョン:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
Timezone(`TimeZone.getDefault()`):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN

ベストアンサー1

上海では12月31日にタイムゾーンが変わります。

見るこのページ1927 年の上海の詳細については、こちらをご覧ください。基本的に、1927 年の終わりの真夜中に、時計は 5 分 52 秒戻りました。したがって、「1927-12-31 23:54:08」は実際には 2 回発生しており、Java はそれをそのローカル日付/時刻の後の可能な瞬間として解析しているようです。これが違いの理由です。

奇妙で素晴らしい時間帯の世界における、またひとつのエピソードです。

バージョン2013aで再構築した場合トルコ元の質問では、まったく同じ動作は示されなくなりました。2013a では、結果は 358 秒になり、遷移時間は 23:54:08 ではなく 23:54:03 になります。

野田タイムでこのような質問を募集しているので、これに気づきました。ユニットテスト... テストは現在変更されていますが、これは単に、履歴データでさえ安全ではないことを示しています。

TZDB 2014f では、変更の時刻は 1900-12-31 に移動され、変更はわずか 343 秒になりました (つまり、 から までの時間tt+1344 秒です)。


1900 での移行に関する質問に答えると、Java タイム ゾーン実装では、1900 UTC の開始前の任意の瞬間にすべてのタイム ゾーンが標準時間にあると単純に扱われるようです。

import java.util.TimeZone;

public class Test {
    public static void main(String[] args) throws Exception {
        long startOf1900Utc = -2208988800000L;
        for (String id : TimeZone.getAvailableIDs()) {
            TimeZone zone = TimeZone.getTimeZone(id);
            if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
                System.out.println(id);
            }
        }
    }
}

上記のコードは、私の Windows マシンでは出力を生成しません。したがって、1900 年初頭の標準以外のオフセットを持つタイム ゾーンは、遷移としてカウントされます。TZDB 自体にはそれより前のデータがあり、「固定」標準時間 (getRawOffset有効な概念であると想定されているもの) という考えに依存していないため、他のライブラリでこの人工的な遷移を導入する必要はありません。

おすすめ記事