2017-03-13 3 views
1

Linux仮想マシン上でcronジョブとして実行されるJavaプログラムがあります。夏時間は、今日、それが決定された後、システムの日付が正しく設定されていなかった 新しいjava.util.Date()を使用してDSTの遅れを返す

String date = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date()); 

それが更新されませんでした

として:現在の問題は、次の行が現在の日付と時刻を格納するためのログの一部として使用され、あります。次のコマンドを使用してこれを修正し、Linux環境を再起動すると、夏時間の日付が正しく更新されます。

ln -s /usr/share/zoneinfo/America/New_York /etc/localtime 

Javaプログラムは、cronジョブの一部として実行したときただし、日付はまだ時間遅れています。これにより、現在のシステム時刻を取得するためにnew Date()が使用されるため、内部的にタイミングの問題が発生し、プロセスで後で問題が発生します。たとえば、午後5時に、Javaプログラムは午後4時を出力します。この実装にはさらに考慮すべき点はありますか? new Date()は常に現在のシステム日付を返してはいけませんか?

cronジョブにデバッグ行を追加すると、これは予想される正しい時刻で実行されます。

+1

おそらく何も変わらないでしょうが、代わりに 'LocalDateTime.now()'を試すことができますか?私は 'Date API'がちょっとしたバグ/欠陥があると聞いたことを覚えています。 – smttsp

答えて

2

TL; DR

  • Instant.now()
  • Update UTCであなたのJVMのtzdata
  • 作業、特にあなたのログ
  • Serializeを

Dateクラス

0 ISO 8601フォーマットには、

新しいDate()は常に現在のシステム日付を返さないはずですか?

はい、Dateクラスは、現在の瞬間を常にUTCで取得します。それを繰り返してみましょう:DateはUTCでの瞬間をキャプチャします。

トラブルがJVMの現在のデフォルトのタイムゾーンは、その文字列を生成する際に適用されるクラスのtoString方法の善意が、不幸な「機能」から来ています。これは時代遅れで厄介なクラスを避けるための多くの理由の1つです。

"tzdata"タイムゾーンデータファイルが古く、DSTカットオーバの新しい日付を認識していない可能性があります。起動時

再起動JVM

Javaの実装は、典型的には、ホストOSから自分の現在のデフォルトのタイムゾーンを拾います。 JVM後、ホストOSのタイムゾーンを変更してもJVMには影響しません。

JVMを再起動して、ホストOSで新しいゾーン設定を取得します。サーバ

ベストプラクティスに

使用UTCは、UTCにサーバーを設定することが通常です。次に、夏時間のナンセンスについて心配する必要はありません。あなたのプログラミング、ロギング、cronジョブ、データ交換、およびデータのシリアル化の大部分はUTCであるべきUTC

作業。

例えば、Stack Overflowが "today"と "yesterday"のアクティビティを報告する際にUTCをどのように使用するかを注意してください。 UTCをThe One True Timeと考えることを学ぶ。すべてのゾーンはそのテーマのバリエーションです。

特定のゾーンを予期しているユーザーにプレゼンテーションなどのクリティカルな場所にのみタイムゾーンを適用します。

あなたの問題は、時空の曲げによるものではなかったことに注意してください。秒、分、および時間は、通常どおり、ティック・トック・ティック・トックをUTCの点で増加し続けました。あなたの問題は、タイムゾーンルールの変更データが古くなっているタイムゾーンに間違っていました。

は、Javaコード内でご希望のゾーンを指定

あなたのJavaアプリケーションは、常に自分の希望/目的とする時間帯を明示的に指定する必要があります。これを省略すると、JVMの現在のデフォルトのタイムゾーンが暗黙的に適用されます。

JVMのデフォルトは、JVM内の任意のアプリケーションの任意のスレッドの任意のコードによっていつでも変更でき、そのJVM内の他のすべてのコードに即座に影響します。だから、重要なことのためにその現在のデフォルトに決して依存しないでください。ユーザーと確認し、コードに明示的に指定します。

避けレガシー日時クラス

DateCalendarを含む古い日付時刻クラスは血まみれです。それらを避けてください。それらは今や古くなり、java.timeクラスに取って代わられています。

Instantクラスはナノ秒単位の分解能を持つタイムライン上の瞬間です。常にUTCです。

Instant instant = Instant.now() ; 

toStringを呼び出し、標準のISO 8601フォーマットされた文字列を生成するには。最後の Zはズールーの略でUTCを意味します。

String output = instant.toString() ; 

2017-01-23T12:34:あなたの全体の問題を回避するコードのこれら2本の単純なラインを使用して56.123456789Z

しかし、あなたは日常でのtzdataを更新する必要があります。

  • ホストOS
  • JVM
  • データベースシステム(Postgresの、など)などジョダタイムとして
  • ライブラリ
+0

偉大な答えをありがとう、私は詳細な説明に感謝します。私は日付との不満の私の公正な分け前をヒットしました、それはリファクタリングを考慮する時間のように思える! – CCrew

関連する問題