Erzwingen Sie die Java-Zeitzone als GMT/UTC

Lesezeit: 7 Minuten

Benutzer-Avatar
SyBer

Ich muss alle zeitbezogenen Operationen auf GMT/UTC erzwingen, unabhängig von der auf dem Computer eingestellten Zeitzone. Gibt es eine bequeme Möglichkeit, dies im Code zu tun?

Zur Verdeutlichung verwende ich die DB-Serverzeit für alle Operationen, aber sie wird gemäß der lokalen Zeitzone formatiert ausgegeben.

Vielen Dank!

  • Eigentlich ist sein Problem eine Teilmenge von mir, aber ich habe eine Lösung gefunden.

    – SyBer

    13. April 2010 um 8:31 Uhr

  • Sehen Sie sich die doppelte Frage an und suchen Sie nach „Joda“ und „DateTimeZone“.

    – Basilikum Bourque

    10. September 2014 um 16:43 Uhr

Benutzer-Avatar
Kevin Brock

Das OP beantwortete diese Frage, um die Standardzeitzone für eine einzelne Instanz einer laufenden JVM zu ändern, setze die user.timezone Systemeigenschaft:

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

Wenn Sie beim Abrufen von Datums-/Uhrzeit-/Zeitstempelobjekten aus einer Datenbank bestimmte Zeitzonen festlegen müssen ResultSetverwenden Sie die zweite Form von getXXX Methoden, die a Calendar Objekt:

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

Oder setzen Sie das Datum in einem PreparedStatement:

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

Dadurch wird sichergestellt, dass der in der Datenbank gespeicherte Wert konsistent ist, wenn die Datenbankspalte keine Zeitzoneninformationen enthält.

Das java.util.Date und java.sql.Date Klassen speichern die tatsächliche Zeit (Millisekunden) in UTC. Um diese bei der Ausgabe in eine andere Zeitzone zu formatieren, verwenden Sie SimpleDateFormat. Sie können dem Wert auch eine Zeitzone zuordnen, indem Sie ein Kalenderobjekt verwenden:

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

Nützliche Referenz

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

  • Beachten Sie beim Festlegen der Zeitzone für die gesamte JVM, dass sie sich auf alles auswirkt, einschließlich solcher Dinge wie die Protokollierung. Nur etwas zu beachten, wenn das der gewünschte Effekt ist.

    – Hermann Hans

    13. April 2010 um 10:16 Uhr

  • Ja, so fein. Nur ein Punkt zu erwähnen, dass ich die user.timezone tatsächlich direkt im Code gesetzt habe, anstatt über den Parameter -D.

    – SyBer

    13. April 2010 um 21:10 Uhr

  • @SyBer: Das funktioniert, aber Sie müssen sicherstellen, dass Sie dies festlegen, bevor eine Methode die Methode TimeZone.getDefault() aufruft. Wenn nicht, werden Sie etwas verwirrt sein, da der Standardwert nach der ersten Ausführung zwischengespeichert wird. Dies bedeutet auch, dass es ein Problem sein könnte, wenn Sie dies innerhalb einer API/Bibliothek tun (versteckt vor der bloßen Ansicht) – achten Sie darauf, ausführlich zu dokumentieren, was Sie tun.

    – Kevin Brock

    14. April 2010 um 0:24 Uhr

Benutzer-Avatar
MG-Entwickler

Auch wenn Sie die JVM-Zeitzone auf diese Weise einstellen können

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

oder -Duser.timezone=GMT in den JVM-Argumenten.

  • System.setProperty("user.timezone" ...) funktioniert nicht.

    – wilmol

    14. Juli 2020 um 3:31 Uhr


  • System.setProperty(“user.timezone”, “EST”); das funktioniert gut. Vielen Dank

    – Pravin Kottawar

    18. Februar 2021 um 8:13 Uhr

Benutzer-Avatar
Snorbi

Sie können die Zeitzone mit ändern Zeitzone.setDefault():

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

  • Nichts für ungut, aber die vorübergehende Änderung eines globalen statischen Zustands klingt nach einer sehr schlechten Idee …

    – G. Demecki

    21. Juni 2017 um 13:56 Uhr

  • Du könntest, aber du solltest nicht. Das ist ein außerordentlich schlechter Rat. Die gesamte JVM hat ihre Zeitzone geändert.

    – schott

    24. Januar 2019 um 13:17 Uhr


  • Manchmal ist es genau das, was man erreichen möchte. Z.B. Ich habe Java-basierte Microservices gesehen, die immer mit UTC laufen, um Zeitzonenprobleme zu vermeiden. In diesen Systemen läuft auch das Datenbank-Backend mit UTC, daher ist es naheliegend, auch die JVM auf UTC zu „zwingen“. Was wichtig ist: Sie müssen wissen, was Sie tun und was die Konsequenzen sind…

    – snorbi

    24. Januar 2019 um 13:27 Uhr


  • absolut nicht. Wenn Sie Ihr gesamtes System in UTC haben möchten (eine sehr gute Idee), setzen Sie die Systemzeitzone auf UTC und lassen Sie die Java-Zeitzone in Ruhe.

    – schott

    24. Februar 2019 um 3:25 Uhr

  • Außer wenn Sie mehrere JVMs mit unterschiedlichen Anforderungen haben. Wir können ewig streiten, aber jeder Fall ist einzigartig: Manchmal müssen Sie die Zeitzone des gesamten Systems einstellen, manchmal nur eine JVM. Seien wir froh, dass die heutigen Systeme so flexibel sind, dass wir beides können 😉

    – snorbi

    24. Februar 2019 um 8:50 Uhr

Benutzer-Avatar
Todd

Ich musste die JVM-Zeitzone für Windows 2003 Server einstellen, weil es immer GMT für new Date();

-Duser.timezone=America/Los_Angeles

Oder Ihre entsprechende Zeitzone. Eine Liste der Zeitzonen zu finden, erwies sich auch als etwas herausfordernd …

Hier sind zwei Listen;

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

Benutzer-Avatar
Basil Bourque

tl;dr

String sql = "SELECT CURRENT_TIMESTAMP ;
…
OffsetDateTime odt = myResultSet.getObject( 1 , OffsetDateTime.class ) ;

Vermeiden Sie die Abhängigkeit vom Hostbetriebssystem oder der JVM für die Standardzeitzone

Ich empfehle Ihnen, Ihren gesamten Code so zu schreiben, dass die gewünschte/erwartete Zeitzone explizit angegeben wird. Sie müssen sich nicht auf die aktuelle Standardzeitzone der JVM verlassen. Beachten Sie außerdem, dass sich die aktuelle Standardzeitzone der JVM ändern kann jeder Zeit während der Laufzeit, mit beliebigem Code in jedem Thread eines beliebigen App-Aufrufs TimeZone.setDefault. Ein solcher Aufruf wirkt sich sofort auf alle Apps innerhalb dieser JVM aus.

java.time

Einige der anderen Antworten waren richtig, sind aber jetzt veraltet. Die schrecklichen Date-Time-Klassen, die mit den frühesten Java-Versionen gebündelt waren, waren fehlerhaft und wurden von Leuten geschrieben, die die Komplexität und Feinheiten der Date-Time-Behandlung nicht verstanden.

Die Legacy-Datums-Uhrzeit-Klassen wurden durch die ersetzt java.time Klassen definiert in JSR 310.

Um eine Zeitzone darzustellen, verwenden Sie ZoneId. Um einen Offset von UTC darzustellen, verwenden Sie ZoneOffset. Ein Offset ist lediglich eine Anzahl von Stunden-Minuten-Sekunden vor oder hinter dem Nullmeridian. Eine Zeitzone ist viel mehr. Eine Zeitzone ist ein Verlauf vergangener, gegenwärtiger und zukünftiger Änderungen des Offsets, der von den Menschen einer bestimmten Region verwendet wird.

Ich muss alle zeitbezogenen Operationen auf GMT/UTC zwingen

Verwenden Sie für einen Offset von null Stunden-Minuten-Sekunden die Konstante ZoneOffset.UTC.

Instant

Um den aktuellen Moment in UTC zu erfassen, verwenden Sie eine Instant. Diese Klasse repräsentiert einen Moment in UTC, per Definition immer in UTC.

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

ZonedDateTime

Um denselben Moment durch die von den Menschen einer bestimmten Region verwendete Wanduhrzeit zu sehen, stellen Sie sich auf eine Zeitzone ein. Gleicher Moment, gleicher Punkt auf der Zeitachse, andere Uhrzeit.

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

Datenbank

Sie erwähnen eine Datenbank.

Um einen Moment aus der Datenbank abzurufen, sollte Ihre Spalte einen Datentyp haben, der dem SQL-Standard entspricht TIMESTAMP WITH TIME ZONE. Rufen Sie ein Objekt statt einer Zeichenfolge ab. In JDBC 4.2 und höher können wir austauschen java.time Objekte mit der Datenbank. Das OffsetDateTime wird von JDBC benötigt, während Instant & ZonedDateTime sind optional.

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

In den meisten Datenbanken und Treibern würde ich vermuten, dass Sie den Moment so erhalten, wie er in UTC angezeigt wird. Aber wenn nicht, können Sie die Anpassung auf zwei Arten vornehmen:

  • Extrahieren Sie a Instant: odt.toInstant()
  • Passen Sie den angegebenen Offset auf einen Offset von Null an: OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;`.

Tabelle der Datums- und Uhrzeittypen in Java (sowohl Legacy als auch Modern) und in Standard-SQL


Um java.time

Das java.time Framework ist in Java 8 und höher integriert. Diese Klassen ersetzen die lästigen alten Erbe Datum-Zeit-Klassen wie z java.util.Date, Calendar& SimpleDateFormat.

Weitere Informationen finden Sie unter Oracle-Tutorial. Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Spezifikation ist JSR310.

Das Joda-Zeit Projekt, jetzt in Wartungsmodusrät zur Migration in die java.time Klassen.

Sie dürfen umtauschen java.time Objekte direkt mit Ihrer Datenbank. Verwenden ein JDBC-Treiber gemäß JDBC 4.2 oder später. Keine Notwendigkeit für Saiten, keine Notwendigkeit für java.sql.* Klassen.

Wo erhalte ich die java.time-Klassen?

  • Java SE 8, Java SE 9, JavaSE 10, Java SE 11und höher – Teil der Standard-Java-API mit einer gebündelten Implementierung.
    • Java 9 fügt einige kleinere Funktionen und Korrekturen hinzu.
  • Java SE 6 und Java SE 7
    • Die meisten von den java.time Funktionalität ist zurückportiert auf Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Spätere Versionen von Android-Bundle-Implementierungen der java.time Klassen.
    • Für frühere Android-Versionen (<26) ist die ThreeTenABP Projekt passt ThreeTen-Backport (oben erwähnt). Sehen Wie benutzt man ThreeTenABP….

Benutzer-Avatar
Paul

für mich nur schnell 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"));
  }

Formatieren Sie dann das Datum mit einer anderen Zeitzone.

Benutzer-Avatar
Dawid Stępień

Systemeigenschaft verwenden:

-Duser.timezone=UTC

  • Warum sollte man das verwenden? Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu, damit andere daraus lernen können

    – Nico Haase

    9. April 2019 um 7:25 Uhr

1312850cookie-checkErzwingen Sie die Java-Zeitzone als GMT/UTC

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy