From 08c328c6cffb57424365341572cb421a0bf6011c Mon Sep 17 00:00:00 2001 From: David Byron Date: Mon, 7 Jul 2014 13:48:42 -0700 Subject: [PATCH] include the time zone name when serializing DateTimes, not just the offset from UTC --- .../joda/deser/DateTimeDeserializer.java | 22 ++++++++++++++++--- .../datatype/joda/ser/DateTimeSerializer.java | 6 ++++- .../datatype/joda/ser/JacksonJodaFormat.java | 5 ++++- .../jackson/datatype/joda/DateTimeTest.java | 6 ++--- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/datatype/joda/deser/DateTimeDeserializer.java b/src/main/java/com/fasterxml/jackson/datatype/joda/deser/DateTimeDeserializer.java index 92b5753d..74da537b 100644 --- a/src/main/java/com/fasterxml/jackson/datatype/joda/deser/DateTimeDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/datatype/joda/deser/DateTimeDeserializer.java @@ -9,6 +9,7 @@ import org.joda.time.DateTime; import org.joda.time.DateTimeZone; +import org.joda.time.LocalDateTime; import org.joda.time.ReadableDateTime; import org.joda.time.ReadableInstant; @@ -53,10 +54,25 @@ public ReadableDateTime deserialize(JsonParser jp, DeserializationContext ctxt) if (str.length() == 0) { // [JACKSON-360] return null; } - if (ctxt.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) - return new DateTime(str, dtz); - else + // Split the string at the first slash. If there's no first + // slash, assume we're dealing with an ISO8601 serialization. + int firstSlash = str.indexOf('/'); + if (firstSlash == -1) { + if (ctxt.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) { + return new DateTime(str, dtz); + } + return DateTime.parse(str); + } + + // Parse our custom serialized format with the explicit time zone identifier + String dateTimeStr = str.substring(0,firstSlash - 1); + String zoneStr = str.substring(firstSlash + 1); + + LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr); + DateTimeZone zone = DateTimeZone.forID(zoneStr); + + return localDateTime.toDateTime(zone); } // TODO: in 2.4, use 'handledType()' throw ctxt.mappingException(getValueClass()); diff --git a/src/main/java/com/fasterxml/jackson/datatype/joda/ser/DateTimeSerializer.java b/src/main/java/com/fasterxml/jackson/datatype/joda/ser/DateTimeSerializer.java index 29f6856e..4a21ac40 100644 --- a/src/main/java/com/fasterxml/jackson/datatype/joda/ser/DateTimeSerializer.java +++ b/src/main/java/com/fasterxml/jackson/datatype/joda/ser/DateTimeSerializer.java @@ -9,13 +9,17 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; +import org.joda.time.format.DateTimeFormatterBuilder; import org.joda.time.format.ISODateTimeFormat; public final class DateTimeSerializer extends JodaDateSerializerBase { protected final static JacksonJodaFormat DEFAULT_FORMAT - = new JacksonJodaFormat(ISODateTimeFormat.dateTime().withZoneUTC()); + = new JacksonJodaFormat(new DateTimeFormatterBuilder().append(ISODateTimeFormat.dateHourMinuteSecondMillis()) + .appendLiteral('/') + .appendTimeZoneId() + .toFormatter()); public DateTimeSerializer() { this(DEFAULT_FORMAT); } public DateTimeSerializer(JacksonJodaFormat format) { diff --git a/src/main/java/com/fasterxml/jackson/datatype/joda/ser/JacksonJodaFormat.java b/src/main/java/com/fasterxml/jackson/datatype/joda/ser/JacksonJodaFormat.java index ba46f6d2..107bb2e6 100644 --- a/src/main/java/com/fasterxml/jackson/datatype/joda/ser/JacksonJodaFormat.java +++ b/src/main/java/com/fasterxml/jackson/datatype/joda/ser/JacksonJodaFormat.java @@ -41,7 +41,10 @@ public class JacksonJodaFormat public JacksonJodaFormat(DateTimeFormatter defaultFormatter) { _useTimestamp = null; - _jdkTimezone = defaultFormatter.getZone().toTimeZone(); + + DateTimeZone zone = defaultFormatter.getZone(); + _jdkTimezone = (zone == null) ? null : zone.toTimeZone(); + _locale = DEFAULT_LOCALE; _formatter = defaultFormatter; _explicitTimezone = false; diff --git a/src/test/java/com/fasterxml/jackson/datatype/joda/DateTimeTest.java b/src/test/java/com/fasterxml/jackson/datatype/joda/DateTimeTest.java index f7da3846..c4c5b623 100644 --- a/src/test/java/com/fasterxml/jackson/datatype/joda/DateTimeTest.java +++ b/src/test/java/com/fasterxml/jackson/datatype/joda/DateTimeTest.java @@ -64,7 +64,7 @@ public void testSerializationFeatureNoTimestamp() throws IOException { ObjectMapper m = jodaMapper(); m.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - assertEquals(quote("1970-01-01T00:00:00.000Z"), m.writeValueAsString(DATE_JAN_1_1970_UTC)); + assertEquals(quote("1970-01-01T00:00:00.000/UTC"), m.writeValueAsString(DATE_JAN_1_1970_UTC)); } public void testAnnotationAsText() throws IOException @@ -72,7 +72,7 @@ public void testAnnotationAsText() throws IOException ObjectMapper m = jodaMapper(); m.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // with annotations, doesn't matter if mapper configured to use timestamps - assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000Z'}"), + assertEquals(aposToQuotes("{'date':'1970-01-01T00:00:00.000/UTC'}"), m.writeValueAsString(new DateAsText(DATE_JAN_1_1970_UTC))); } @@ -94,7 +94,7 @@ public void testSerializationWithTypeInfo() throws IOException ObjectMapper m = jodaMapper(); m.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); m.addMixInAnnotations(DateTime.class, ObjectConfiguration.class); - assertEquals("[\"org.joda.time.DateTime\",\"1970-01-01T00:00:00.000Z\"]", + assertEquals("[\"org.joda.time.DateTime\",\"1970-01-01T00:00:00.000/UTC\"]", m.writeValueAsString(dt)); } }