3

起動時に -Duser.timezone パラメータを使用する Java プログラムがあります。

-Duser.timezone="CET"

サーバーの内部クロックに頼ることができないため、これが必要です (管理者が遊んだり、間違ったタイムゾーンを設定したりするなど、質問しないでください :-( )。フロントエンドのタイムゾーンがバックエンドと一致することが重要です。

このプログラムは定期的に再起動されないため (これはサーバーです)、冬から夏に切り替えるとどうなるのだろうと思っていました。自動的に切り替わりますか、それともサーバーを再起動する必要がありますか?

よろしくお願いします、アレックス

編集:日付を使用する関数を呼び出すたびに、Javaが正しいタイムゾーンを決定する可能性があります。しかし、Java が起動時に正しいタイムゾーンを決定する可能性もあります。

4

3 に答える 3

2

Java の時間は、タイム ゾーンに関する情報を含まない単純な long 値 (1970 年以降のミリ秒) です。またjava.util.Datejava.sql.Date日付/時刻は 1970 年以降のミリ秒単位で内部的に保存されますが、UTC タイム ゾーンが使用されます。

タイムゾーンは、出力用に日付/時刻をフォーマットするとき、または文字列から日付/時刻を解析するときに使用されます。その際、 で設定したタイムゾーン情報-Duser.timezoneが使用されます。

したがって、それは機能するはずであり、少しのテストでもそれが示されます:

public static void main(String[] args) {
    Calendar c = Calendar.getInstance();
    c.set(2013, 2, 30, 23, 0, 0);
    long start = c.getTimeInMillis();
    long oneHour = 1000 * 60 * 60;
    long t = start;
    for (long i = 0; i < 5; i++) {
        System.out.println(new Date(t));            
        t = t + oneHour;
    }
}

それを使用-Duser.timezone=GMTすると、次のように出力されます:(スイッチなし)

Sat Mar 30 23:00:00 GMT 2013
Sun Mar 31 00:00:00 GMT 2013
Sun Mar 31 01:00:00 GMT 2013
Sun Mar 31 02:00:00 GMT 2013
Sun Mar 31 03:00:00 GMT 2013

それを使用-Duser.timezone=CETすると、次のように出力されます:(午前2時に切り替え)

Sat Mar 30 23:00:00 CET 2013
Sun Mar 31 00:00:00 CET 2013
Sun Mar 31 01:00:00 CET 2013
Sun Mar 31 03:00:00 CEST 2013
Sun Mar 31 04:00:00 CEST 2013

これを使用-Duser.timezone=EETすると、次のように出力されます: (東ヨーロッパ時間、CET の 1 時間後)

Sat Mar 30 23:00:00 EET 2013
Sun Mar 31 00:00:00 EET 2013
Sun Mar 31 01:00:00 EET 2013
Sun Mar 31 02:00:00 EET 2013
Sun Mar 31 04:00:00 EEST 2013
于 2013-02-20T14:00:08.043 に答える
0

user.timezoneのようにデフォルトのタイムゾーンを設定すると確信していますTimeZone.setDefault()。そのため、夏時間やその他の変更については更新されません。

本当にこれを行う必要がある場合は、を呼び出してタイムゾーンを変更できるサーバーへのカスタムリクエストを作成することをお勧めしますTimeZone.setDefault()。このようにして、必要に応じてサーバーを再起動せずに変更できます。明らかに、このリクエストは、管理者のみが実行できるように保護する必要があります。

于 2013-02-20T13:57:50.707 に答える
0

CET疑似ゾーンです

ESTまたはなどの 2 ~ 4 文字の略語は決して使用しないでください。それらISTは実際のタイム ゾーンではなく、標準化されておらず、一意でさえありません (!)。

Continent/Region

、、、などの適切なタイム ゾーン名を の形式で指定します。Continent/RegionAmerica/MontrealAfrica/CasablancaPacific/Auckland

おそらく、CET実際にはEurope/Luxembourgやなどのタイムゾーンを意味していますEurope/Gibraltar

ZoneId zoneId = ZoneId.of( "Europe/Gibralter" ) ;

このTimeZoneクラスは現在レガシーであり、初期バージョンの Java にバンドルされていた恐ろしい日時クラスの一部です。代わりに最新のjava.timeクラスのみを使用してください。

適切な名前は DST に合わせて調整されます

このプログラムは定期的に再起動されないため (これはサーバーです)、冬から夏に切り替えるとどうなるのだろうと思っていました。

上記のように適切な名前を使用し、JVM インストールでtzdataデータ ファイルを最新の状態に保つと、使用時に夏時間 (DST) カットオーバーが自動的に処理されますZonedDateTime

ZonedDateTime zdt = ZonedDateTime.now() ;  // Omitting the optional `ZoneId` argument means the JVM’s current default time zone is implicitly applied, looking up the current offset in use at this moment for the JVM's current default time zone.

3 月 29 日の午前 2 時に、2020 年春の DST カットオーバー中に何が起こるか見てみましょう。時刻は午前 2 時 1 分前です。次に、1 分追加します。DST のウォールクロック時間の「スプリングアヘッド」調整により、時刻が午前 2 時ではなく午前 1 時 59 分から午前 3 時にジャンプすることに注意してください。

ZoneId z = ZoneId.of( "Europe/Gibraltar" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 3 , 29 , 1 , 59 , 0 , 0 , z ) ;
ZonedDateTime zdtMinuteLater = zdt.plusMinutes( 1 ) ;  // Notice how the time-of-day jumps to 3 AM rather than 2 AM.

コンソールにダンプします。

System.out.println( "zdt.toString(): " + zdt ) ;
System.out.println( "zdtMinuteLater.toString(): " + zdtMinuteLater ) ;

IdeOne.com でこのコードのライブ実行を参照してください。

zdt.toString(): 2020-03-29T01:59+01:00[ヨーロッパ/ジブラルタル]

zdtMinuteLater.toString(): 2020-03-29T03:00+02:00[ヨーロッパ/ジブラルタル]

デフォルトに頼らない

JVM の現在のデフォルト タイム ゾーンに依存しないようにコードを記述できます。

前に示したコード行 ( ZonedDateTime.now()) は、私が推奨するものではありません。ZoneIdその行では、オプションの引数が省略されています。代わりに、希望する/予想されるタイムゾーンを常に渡すことをお勧めします。

ZoneId zoneId = ZoneId.of( "Europe/Gibralter" ) ;
ZonedDateTime zdtGibralter = ZonedDateTime.now( zoneId ) ;
于 2020-01-28T03:53:41.040 に答える