it-swarm.com.de

Standardzeitzone für DateTime-Deserialisierung mit Jackson (Joda-Time-Modul)

Bei dieser Frage geht es um die Deserialisierung zu Joda-TimeDateTime mit jackson-datatype-joda-Modul für Jackson. Gibt es eine Standard-Zeitzone, in die Datumszeichenketten deserialisiert werden? Wenn ja, was ist das? Ist es UTC?

Ich muss das fragen, weil die Jackson-Dokumentation nicht spezifisch für Joda-Time DateTime ist. Ich habe in diesem Artikel ( http://wiki.fasterxml.com/JacksonFAQDateHandling ) festgestellt, dass Jackson GMT als Standardzeitzone für die Deserialisierung in Java.util.Date oder Java.util.Calendar nimmt . Joda-Time-Datentypen werden in diesem Dokument jedoch nicht erwähnt. Darüber hinaus brauche ich insbesondere Strings, um in DateTime-Objekte mit der Zeitzone UTC zu deserialisieren, nicht in GMT: Obwohl diese beiden Zonen sehr ähnlich sind, gibt es einige kleine Unterschiede, und daher ist GMT für mich nicht machbar .

Vielen Dank.

16
ecbrodie

Der Quellcode für DateTimeDeserializer zeigt, dass er die Zeitzone von DeserializationContext verwendet, die während der Deserialisierung von ObjectMapper bereitgestellt wird. Wenn Sie sich die ObjectMapper API ansehen, sehen Sie eine Methode zum Einstellen der Zeitzone:

public ObjectMapper setTimeZone(TimeZone tz)

Daher können Sie diese Methode verwenden, um Ihre ObjectMapper zu konfigurieren und die Zeitzone auf die richtige einzustellen.

Was den Standardwert angeht, scheint der Javadoc eine Sache zu sagen, der Code zeigt jedoch eine andere.

Javadoc für ObjectMapper.setTimeZone(TimeZone tz):

/**
  * Method for overriding default TimeZone to use for formatting.
  * Default value used is {@link TimeZone#getDefault()}.
  */

Der Code setzt die Zeitzone jedoch explizit auf:

protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
    ...
    // TimeZone.getDefault()
    TimeZone.getTimeZone("GMT"),
    ...

Anscheinend verwendet es tatsächlich GMT und nicht den Standard-Standard der JVM.

Ich würde sagen, dass es wahrscheinlich die beste Wahl wäre, sich nicht darauf zu verlassen und es selbst auf ObjectMapper.setTimeZone(TimeZone tz) zu setzen.

22
Redder

UTC vs. GMT

Bei Business-Apps gibt es keinen praktischen Unterschied zwischen UTC und GMT . Der einzige Unterschied bezieht sich auf die Auflösung in Sekundenschnelle und eine alle zwei Jahre hinzugefügte Sprungsekunde . Für Wissenschaft, Astronomie, Satellitennavigation und solche Apps kann der Unterschied erheblich sein, aber das ist selten.

Jackson ist standardmäßig auf UTC/GMT eingestellt

Ich weiß es nicht Jackson. Wenn Sie jedoch das verknüpfte Dokument betrachten, werden die Zeilen entweder (a) die Anzahl der Millisekunden seit dem 1. Januar 1970, UTC oder (b) eines Zeichenkettenformats serialisiert. Der Standardwert ist ISO 8601 format: " 1970-01-01T00: 00: 00.000 + 0000 ". Um Ihre Frage nach Zeitzonen zu beantworten, klingt es so, als würde Jackson standardmäßig immer UTC (keine Zeitzonenverschiebung) serialisieren, was der richtige Weg ist. Wenn Sie sich für die Zeitzone interessieren, die zu dieser Zeit verwendet wurde, sollten Sie diese Tatsache (welche Zeitzone) in einem separaten Feld aufzeichnen.

Jackson ↔ Java.util.Date/Calendar ↔ Joda-Time

Beide seriellen Werte (Millisekunden und ISO 8601-Zeichenfolge) können mit Konstruktoren für Joda-Time DateTime -Instanzen verwendet werden.

String dateTimeString = "2013-11-22T18:37:55.645+0000";
org.joda.time.DateTime myDateTime = org.joda.time.format.ISODateTimeFormat.dateTime().withZoneUTC().parseDateTime( dateTimeString );

und…

Long millisSinceEpoch = 1385495462L;
org.joda.time.DateTime myDateTime = new org.joda.time.DateTime( millisSinceEpoch );

Wenn Sie keinen direkten Zugriff auf diese serialisierten Werte haben, um sie an Joda-Time-DateTime-Konstruktoren weiterzuleiten, lassen Sie die Java.util.Date/Calendar-Objekte von Jackson instanziieren. Versorgen Sie Joda-Time mit diesen Java.util.Date/Calendar-Objekten, um DateTime-Objekte für die weitere Arbeit zu instanziieren. Joda-Time-Benutzer machen dies häufig.

org.joda.time.DateTime myDateTime = new org.joda.time.DateTime( someJavaUtilDateFromJackson );

Sie können diese UTC-Zeit problemlos in andere Zeitzonen in Joda-Time konvertieren, indem Sie die Methode toDateTime () aufrufen und die gewünschte Zeitzone übergeben.

org.joda.time.DateTimeZone kolkataTimeZone = org.joda.time.DateTimeZone.forID( "Asia/Kolkata" );
org.joda.time.DateTime dateTimeInKolkata = myDateTime.toDateTime( kolkataTimeZone ); 

Joda-Time konvertiert problemlos mit der Methode toDate nach Java.util.Date. Machen Sie die meiste Arbeit in Joda-Time und konvertieren Sie sie wieder in Java.util.Date, um mit Jackson zu kommunizieren. Und als ich zu Jackson zurückkehrte, würde ich meine DateTimes nur aus gutem Grund auf UTC umstellen.

myDateTime.toDateTime( org.joda.time.DateTimeZone.UTC )

Auf StackOverflow.com finden Sie viele Beispiele für die oben genannten Joda-Time-Vorgänge.

Mach es einfach

Ich vermute, Sie machen sich etwas zu viel Sorgen und zu wenig Codierung. Versuchen Sie einfach ein paar kleine Experimente, indem Sie Werte in und aus Jackson und Joda-Time eingeben. Sie werden schnell den Dreh raus haben. Ich empfehle Ihnen, dass Sie Jackson tun lassen, was es standardmäßig tun möchte, und dann in Joda-Time manipulieren. Joda-Time wurde für die kniffligen Probleme von Datum und Uhrzeit entwickelt, und Jackson ist vermutlich nicht der Fall. Joda-Time verfügt sowohl über Konstruktoren als auch über Methoden, um die Zeitzonen nach Wunsch anzupassen.

Eine hellere Zukunft

In Java 8 bietet JSR 310: Date and Time API Joda-Time-ähnliche Klassen in die Java-Plattform. Erwarten Sie, dass Frameworks wie Jackson aktualisiert werden, um direkt mit diesen neuen Klassen zu arbeiten, während Sie die hässlichen Java.util.Date/Calendar-Klassen ablehnen.

Es sieht so aus, als würde das jackson-datatype-joda-Projekt Ihnen jetzt diese Bequemlichkeit für Joda-Time bringen. Aber es erscheint mir nicht notwendig. Sie können einfach zwischen Java.util.Date/Calendar und Joda-Time wie oben beschrieben konvertieren.

P.S. Der "Wiki" -Link für die Projektdokumentation schlägt fehl. So konnte ich nicht ihren Doc sehen.

17
Basil Bourque

Ich hatte auch Probleme mit Datumsformaten und fand schließlich eine Lösung. Ich wollte das Format "2016-02-08T12:49:22.876Z" verwenden, da es ISO 8601 ist und von JavaScript Date Object verwendet wird. Ich wollte auch immer die UTC-Zeitzone verwenden. 

Ich habe festgestellt, dass dies mit folgendem Code möglich ist:

final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(dateFormat);

System.out.println(objectMapper.writeValueAsString(new Date()));

Bitte beachten Sie das X-Zeichen in der Formatzeichenfolge. Es wird von Java 7 unterstützt und legt die Zeitzone in ISO 8601 fest. Wie in SimpleDateFormat dokumentiert, erzeugt/Z (anstelle von +00:00), wenn der Zeitzonenversatz 0 (UTC) ist.

3
Vojta

Aus einem einfachen Code habe ich herausgefunden, dass, wenn Jackson ein Deserialize-Date-Objekt aus einem String erstellt, es UTC gibt, wenn keine Zeitzone erwähnt wird, aber wenn es direkt instanziiert wird, dann die Standard-Zeitzone gibt d.

DateTime date = new DateTime(2013, 1, 2, 0, 0) //gives local timezone

Folgendes gibt UTC

ObjectMapper mapper = new ObjectMapper();
DateTime dt = new DateTime(2013, 1, 2, 0, 0);
String serialized = mapper.writeValueAsString(dt);
DateTime dt1 = mapper.readValue(serialized, DateTime.class); //gives UTC
1
Neil