2017-06-08 9 views
0

Haben Sie ein Problem, wo, wenn Uhren wegen einer Sommerzeit (zweimal im Jahr) verschoben werden, Daten in Java nicht korrekt sind (Ich bin in Mitteleuropa: GMT+2 im Sommer, GMT+1 in Winter)Jboss Java Datum Sommerzeit

Wenn die Zeit um 1 Stunde nach vorne verschoben wird, gibt new Date() immer noch die alte Zeit zurück (1 Stunde nach der aktuellen Zeit).

In Java 7, kann dies gelöst werden, ohne die Jboss-Anwendungsserver neu zu starten?

Wenn ich die Zeit manuell in Windows ändern, reproduzieren Sie das Problem: Date wird nicht auf das Systemdatum aktualisiert, wenn jboss neu gestartet wird.

Calendar c = Calendar.getInstance(); 
c.setTime(new Date()); 
+1

Dieses Verhalten bedeutet, dass Sie wahrscheinlich nicht korrekt Zeitzonen verwenden, so dass Sie Vielleicht möchten Sie überprüfen, wie Ihre App mit Zeitstempeln funktioniert. Und Sie möchten vielleicht von "Date" ganz weg migrieren, da diese Klasse meines Wissens keine Zeitzonen oder irgendeine Art von DST-Übergängen unterstützt. Verwenden Sie Klassen aus 'java.time' Paket, oder wenn Sie Java8 noch nicht haben, verwenden Sie mindestens' java.util.Calendar'. –

+4

Ein Date-Objekt hat keine Zeitzoneninformation, es ist nur eine Anzahl von Millis seit der Epoche. Es zeigt beim Drucken die Standardzeitzone an, hat jedoch keinen Einfluss auf den Status. – assylias

+0

verwendete Kalender und setTime (neues Date()). Ich möchte nur das aktuelle Systemdatum ohne Neustart erhalten. Wenn das Systemdatum manuell aktualisiert wird, wird das aktuelle Kalenderdatum ohne Neustart nicht aktualisiert. – kandan

Antwort

2

In Java < = 7, können Sie die ThreeTen Backport verwenden, eine große Rückportierung für Java 8 der neuen Datum/Zeit-Klassen.

Damit können Sie problemlos mit DST-Änderungen umgehen.

Zuerst können Sie die org.threeten.bp.DateTimeUtils von und zu Calendar konvertieren.

Der folgende Code konvertiert die Calendar zu org.threeten.bp.Instant, die eine Klasse, die ein „UTC instant“ (einen Zeitstempel unabhängig von Zeitzone darstellt: gerade jetzt, in diesem Augenblick, jeder in der Welt ist im selben Augenblick, obwohl ihre lokales Datum und Uhrzeit können je nach Standort unterschiedlich sein).

Dann wird die Instant in eine org.threeten.bp.ZonedDateTime konvertiert (was bedeutet: zu diesem Zeitpunkt, was ist das Datum und die Uhrzeit in dieser Zeitzone?). Ich habe auch die org.threeten.bp.ZoneId die Zeitzone zu erhalten:

Calendar c = Calendar.getInstance(); 
c.setTime(new Date()); 

// get the current instant in UTC timestamp 
Instant now = DateTimeUtils.toInstant(c); 

// convert to some timezone 
ZonedDateTime z = now.atZone(ZoneId.of("Europe/Berlin")); 

// today is 08/06/2017, so Berlin is in DST (GMT+2) 
System.out.println(z); // 2017-06-08T14:11:58.608+02:00[Europe/Berlin] 

// testing with a date in January (not in DST, GMT+1) 
System.out.println(z.withMonth(1)); // 2017-01-08T14:11:58.608+01:00[Europe/Berlin] 

Ich habe gerade einige Zeitzone nahm die Mitteleuropa Zeitzone verwendet (Europe/Berlin): Sie können nicht diese 3-Buchstaben-Abkürzungen verwenden, weil sie ambiguous and not standard sind. Sie können den Code in die Zeitzone ändern, die für Ihr System am besten geeignet ist (Sie können eine Liste aller verfügbaren Zeitzonen mit ZoneId.getAvailableZoneIds() erhalten).

Ich ziehe es diese Lösung, weil es explizit ist, welche Zeitzone wir den Benutzer angezeigt werden verwenden (Date und Calendar ‚s toString() Methoden verwenden, um die Standard-Zeitzone hinter den Kulissen und man kann nie wissen, was sie tun).

Und intern können wir weiterhin die Instant verwenden, die in UTC ist, so wird es nicht von Zeitzonen beeinflusst (und Sie können jederzeit zu und von Zeitzonen konvertieren, wann immer Sie benötigen) - wenn Sie die ZonedDateTime zurück zu konvertieren möchten Instant, verwenden Sie einfach die toInstant() Methode.


Eigentlich, wenn Sie das aktuelle Datum/Zeit erhalten möchten, vergessen Sie einfach die alten Klassen (Date und Calendar) und benutzen Sie einfach die Instant:

// get the current instant in UTC timestamp 
Instant now = Instant.now(); 

Aber wenn Sie noch verwenden müssen die alten Klassen, verwenden Sie einfach DateTimeUtils, um die Konvertierungen durchzuführen.


Die Ausgabe der obigen Beispiele sind das Ergebnis des Verfahrens ZonedDateTime.toString(). Wenn Sie das Format ändern möchten, verwenden Sie die org.threeten.bp.format.DateTimeFormatter Klasse (werfen Sie einen Blick auf die javadoc, um weitere Informationen über alle möglichen Formate):

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z X"); 
// DST (GMT+02) 
System.out.println(formatter.format(z)); // 08/06/2017 14:11:58 CEST +02 
// not DST (GMT+01) 
System.out.println(formatter.format(z.withMonth(1))); // 08/01/2017 14:11:58 CET +01