JavaタイムゾーンをGMT / UTCとして強制する


95

マシンに設定されているタイムゾーンに関係なく、時間に関連する操作をGMT / UTCに強制する必要があります。コードでそうするための便利な方法はありますか?

明確にするために、私はすべての操作にDBサーバー時間を使用していますが、ローカルのタイムゾーンに従ってフォーマットされています。

ありがとう!


実際、彼の問題は私のサブセットですが、解決策を見つけました。
SyBer 2010

重複する質問を見て、「Joda」と「DateTimeZone」を検索します。
バジルブルク2014

回答:


124

OPは、実行中のJVMの単一インスタンスのデフォルトのタイムゾーンを変更するには、この質問に答え、設定user.timezoneシステムプロパティを:

java -Duser.timezone=GMT ... <main-class>

データベースからDate / Time / Timestampオブジェクトを取得するときに特定のタイムゾーンを設定する必要がある場合は、オブジェクトを取得するメソッドのResultSet2番目の形式を使用します。getXXXCalendar

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
ResultSet rs = ...;
while (rs.next()) {
    Date dateValue = rs.getDate("DateColumn", tzCal);
    // Other fields and calculations
}

または、PreparedStatementで日付を設定します。

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
PreparedStatement ps = conn.createPreparedStatement("update ...");
ps.setDate("DateColumn", dateValue, tzCal);
// Other assignments
ps.executeUpdate();

これらにより、データベース列にタイムゾーン情報が保持されていない場合でも、データベースに格納されている値の一貫性が保たれます。

java.util.Dateそしてjava.sql.Dateクラスは、UTCでの実際の時間(ミリ秒)を格納します。これらを出力時に別のタイムゾーンにフォーマットするには、を使用しますSimpleDateFormat。Calendarオブジェクトを使用して、タイムゾーンを値に関連付けることもできます。

TimeZone tz = TimeZone.getTimeZone("<local-time-zone>");
//...
Date dateValue = rs.getDate("DateColumn");
Calendar calValue = Calendar.getInstance(tz);
calValue.setTime(dateValue);

便利なリファレンス

https://docs.oracle.com/javase/9​​/troubleshoot/time-zone-settings-jre.htm#JSTGD377

https://confluence.atlassian.com/kb/setting-the-timezone-for-the-java-environment-841187402.html


JVM全体のタイムゾーンの設定について注意すべき点の1つは、ロギングなどを含むすべてに影響を与えることです。それが望ましい効果であるならば、心に留めておくべきことだけです。
Hermann Hans

うん、大丈夫。私が実際にuser.timezoneを設定するのは、-Dパラメーターではなく、コードで直接行うことです。
SyBer 2010

6
@SyBer:機能しますが、メソッドがTimeZone.getDefault()メソッドを呼び出す前に、これを設定する必要があります。そうしないと、デフォルトは最初の実行後にキャッシュされるため、混乱が生じます。これは、API /ライブラリ(プレーンビューでは非表示)内でこれを行うと問題が発生する可能性があることも意味します。必ず何をしているのかを詳しく文書化してください。
Kevin Brockが2010

23

また、JVMタイムゾーンをこの方法で設定できる場合

System.setProperty("user.timezone", "EST");

または-Duser.timezone=GMTJVM引数で。


System.setProperty("user.timezone" ...)動作しません。
ウィルモル

13

Windows 2003 Serverは常に新しいDate()に対してGMTを返すため、JVMタイムゾーンを設定する必要がありました。

-Duser.timezone=America/Los_Angeles

または、適切なタイムゾーン。タイムゾーンのリストを見つけるのも少し難しいことがわかりました...

ここに2つのリストがあります。

http://wrapper.tanukisoftware.com/doc/english/prop-timezone.html

http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzatz%2F51%2Fadmin%2Freftz.htm


9

TimeZone.setDefault()を使用してタイムゾーンを変更できます。

TimeZone.setDefault(TimeZone.getTimeZone("GMT"))

違反はありませんが、一時的にグローバル静的状態を変更することは非常に悪い考えのように聞こえます...
G. Demecki

できますが、すべきではありません。これは非常に悪いアドバイスです。JVM全体のタイムゾーンが変更されています。
スコット

1
時々、それはまさにあなたが達成したいものです。例えば。タイムゾーンの問題を回避するために、Javaベースのマイクロサービスが常にUTCで実行されるのを見てきました。これらのシステムでは、データベースバックエンドもUTCで実行されるため、JVMを強制的にUTCに強制することも自然です。重要なこと:あなたは自分が何をしていて、どんな結果をもたらすかを知らなければなりません...
snorbi

絶対違う。システム全体をUTCで使用したい場合(非常に良いアイデア)、システムのタイムゾーンをUTCに設定し、Javaのタイムゾーンはそのままにしておきます。
スコット

3
ただし、要件が異なる複数のJVMがある場合は除きます。私たちは永遠に議論することができますが、すべてのケースがユニークです。時には、システム全体のタイムゾーンを設定する必要がある場合もあれば、1つのJVMのみを設定する場合もあります。レッツ・今日のシステムは、我々は両方の😉を行うことができるように柔軟であることを幸せに
snorbi

8

私にとっては、簡単なSimpleDateFormat、

  private static final SimpleDateFormat GMT = new SimpleDateFormat("yyyy-MM-dd");
  private static final SimpleDateFormat SYD = new SimpleDateFormat("yyyy-MM-dd");
  static {
      GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
    SYD.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
  }

次に、異なるタイムゾーンで日付をフォーマットします。


6

DBから時間を生の形式(長いタイムスタンプまたはJavaの日付)で取得し、SimpleDateFormatを使用してフォーマットするか、Calendarを使用して操作します。どちらの場合も、使用する前にオブジェクトのタイムゾーンを設定する必要があります。

参照SimpleDateFormat.setTimeZone(..)およびCalendar.setTimeZone(..)詳細については、


6

tl; dr

String sql = "SELECT CURRENT_TIMESTAMP ;

OffsetDateTime odt = myResultSet.getObject( 1 , OffsetDateTime.class ) ;

デフォルトのタイムゾーンをホストOSまたはJVMに依存しないようにする

すべてのコードを記述して、希望する/予想されるタイムゾーンを明示的に示すことをお勧めします。JVMの現在のデフォルトのタイムゾーンに依存する必要はありません。また、JVMの現在のデフォルトのタイムゾーンは、実行中の任意の時点で、任意のアプリの任意のスレッド内の任意のコードで変更れる可能性があることに注意してTimeZone.setDefaultください。このような呼び出しは、そのJVM内のすべてのアプリにすぐに影響します。

java.time

他の回答のいくつかは正しかったが、現在は時代遅れです。Javaの最も初期のバージョンにバンドルされた恐ろしい日時クラスには欠陥があり、日時処理の複雑さと微妙さを理解していない人々によって書かれました。

従来の日時クラスは、JSR 310で定義されたjava.timeクラスに取って代わられました。

タイムゾーンを表すには、を使用しますZoneId。UTCからのオフセットを表すには、を使用しますZoneOffset。オフセットは、本初子午線の前後数時間分秒です。タイムゾーンははるかに大きいです。タイムゾーンは、特定の地域の人々が使用するオフセットに対する過去、現在、および将来の変更の履歴です。

時間関連の操作をGMT / UTCに強制する必要がある

ゼロ時分秒のオフセットには、定数を使用しZoneOffset.UTCます。

Instant

UTCで現在の瞬間をキャプチャするには、を使用しInstantます。このクラスは、定義により常にUTCであるUTCの瞬間を表します。

Instant instant = Instant.now() ;  // Capture current moment in UTC.

ZonedDateTime

特定の地域の人々が使用する実時間を通じて同じ瞬間を確認するには、タイムゾーンに調整します。同じ瞬間、タイムライン上の同じポイント、異なる実時間。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

データベース

あなたはデータベースについて言及しています。

データベースから瞬間を取得するには、列がSQL標準に似たデータ型である必要がありますTIMESTAMP WITH TIME ZONE。文字列ではなくオブジェクトを取得します。JDBC 4.2以降では、java.timeオブジェクトをデータベースと交換できます。OffsetDateTime一方で、JDBCによって必要とされるInstantZonedDateTimeオプションです。

OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;

ほとんどのデータベースとドライバーでは、UTCで見られるような瞬間が得られると思います。ただし、そうでない場合は、次の2つの方法のいずれかで調整できます。

  • を抽出Instantodt.toInstant()
  • 指定されたオフセットからゼロのオフセットに調整します:OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC); `。

Java(レガシーとモダンの両方)および標準SQLの日時タイプの表


java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

java.timeオブジェクトをデータベースと直接交換できます。JDBC 4.2以降に準拠したJDBCドライバーを使用します。文字列もクラスも必要ありません。java.sql.*

java.timeクラスはどこで入手できますか?


1

クライアント/サーバーのペアを作成して、実行後にクライアントサーバーが正しい時刻と日付を送信するようにします。次に、クライアントはサーバーに午後GMTを要求し、サーバーは応答権を送り返します。


1

システムプロパティを使用:

-Duser.timezone=UTC

5
なぜそれを使うべきなのでしょうか?他の人がそれから学ぶことができるように、あなたの答えにいくつかの説明を加えてください
ニコ・ハーセ

1

MySQLで次の行を実行して、タイムゾーンをリセットします。

SET @@global.time_zone = '+00:00';

0

ワオ。私はこれが古いスレッドであることを知っていますが、ユーザーレベルのコードでTimeZone.setDefault()を呼び出さないことだけが言えるでしょう。これは常にJVM全体のタイムゾーンを設定し、ほとんどの場合非常に悪い考えです。joda.timeライブラリとよく似ているJava 8でjoda.timeライブラリまたは新しいDateTimeクラスを使用する方法を学びます。


-6

intigerでのみGMT時間を取得したい場合:var currentTime = new Date(); var currentYear = '2010' var currentMonth = 10; var currentDay = '30 'var currentHours = '20' var currentMinutes = '20 'var currentSeconds = '00' var currentMilliseconds = '00 '

currentTime.setFullYear(currentYear);
currentTime.setMonth((currentMonth-1)); //0is January
currentTime.setDate(currentDay);  
currentTime.setHours(currentHours);
currentTime.setMinutes(currentMinutes);
currentTime.setSeconds(currentSeconds);
currentTime.setMilliseconds(currentMilliseconds);

var currentTimezone = currentTime.getTimezoneOffset();
currentTimezone = (currentTimezone/60) * -1;
var gmt ="";
if (currentTimezone !== 0) {
  gmt += currentTimezone > 0 ? ' +' : ' ';
  gmt += currentTimezone;
}
alert(gmt)

5
私にはJavaScript(!= Java)のように見えます。
Phil
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.