-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,10 +35,29 @@ public boolean isEmpty(SerializerProvider prov, DateTime value) { | |
@Override | ||
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException | ||
{ | ||
if (_useTimestamp(provider)) { | ||
gen.writeNumber(value.getMillis()); | ||
// First: simple, non-timezone-included output | ||
if (!provider.isEnabled(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)) { | ||
if (_useTimestamp(provider)) { | ||
gen.writeNumber(value.getMillis()); | ||
} else { | ||
gen.writeString(_format.createFormatter(provider).print(value)); | ||
} | ||
} else { | ||
gen.writeString(_format.createFormatter(provider).print(value)); | ||
// and then as per [datatype-joda#44], optional TimeZone inclusion | ||
|
||
StringBuilder sb; | ||
|
||
if (_useTimestamp(provider)) { | ||
sb = new StringBuilder(20) | ||
.append(value.getMillis()); | ||
} else { | ||
sb = new StringBuilder(40) | ||
.append(_format.createFormatter(provider).print(value)); | ||
} | ||
sb = sb.append('[') | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
cowtowncoder
Author
Member
|
||
.append(value.getZone()) | ||
.append(']'); | ||
gen.writeString(sb.toString()); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package com.fasterxml.jackson.datatype.joda; | ||
|
||
import org.joda.time.DateTime; | ||
import org.joda.time.DateTimeZone; | ||
|
||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import com.fasterxml.jackson.databind.*; | ||
|
||
// for [datatype-joda#44] | ||
public class TimeZoneTest extends JodaTestBase | ||
{ | ||
// November 3, 2013 at 1:00a is the fall back DST transition that year in much of the US. | ||
private static final int FALL_BACK_YEAR = 2013; | ||
|
||
private static final int FALL_BACK_MONTH = 11; | ||
|
||
private static final int FALL_BACK_DAY = 3; | ||
|
||
// The first one for America/Los_Angeles happens at 8:00 UTC. | ||
private static final int FIRST_FALL_BACK_HOUR = 8; | ||
|
||
// And the second one happens at 9:00 UTC | ||
private static final int SECOND_FALL_BACK_HOUR = 9; | ||
|
||
private static final DateTimeZone AMERICA_LOS_ANGELES = DateTimeZone.forID("America/Los_Angeles"); | ||
|
||
private final DateTime DATE_JAN_1_1970_UTC = new DateTime(0L, DateTimeZone.UTC); | ||
|
||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY, property = "@class") | ||
private static interface TypeInfoMixIn { | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Test methods | ||
/********************************************************** | ||
*/ | ||
|
||
private final ObjectMapper MAPPER = jodaMapper(); | ||
|
||
public void testSimple() throws Exception | ||
{ | ||
// First, no zone id included | ||
ObjectWriter w = MAPPER.writer() | ||
.without(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); | ||
|
||
assertEquals("0", | ||
w.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(DATE_JAN_1_1970_UTC)); | ||
assertEquals(quote("1970-01-01T00:00:00.000Z"), | ||
w.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(DATE_JAN_1_1970_UTC)); | ||
|
||
// then with zone id | ||
|
||
w = w.with(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); | ||
assertEquals(quote("0[UTC]"), | ||
w.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(DATE_JAN_1_1970_UTC)); | ||
assertEquals(quote("1970-01-01T00:00:00.000Z[UTC]"), | ||
w.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(DATE_JAN_1_1970_UTC)); | ||
} | ||
|
||
public void testRoundTrip() throws Exception | ||
{ | ||
ObjectWriter w = MAPPER.writer() | ||
.with(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); | ||
DateTime input = new DateTime(2014, 8, 24, 5, 17, 45, DateTimeZone.forID("America/Chicago")); // arbitrary | ||
|
||
// First as timestamp | ||
|
||
String json = w.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(input); | ||
DateTime result = MAPPER.readValue(json, DateTime.class); | ||
assertEquals("Actual timepoints differ", input.getMillis(), result.getMillis()); | ||
assertEquals("TimeZones differ", input, result); | ||
|
||
// then as regular tet | ||
json = w.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.writeValueAsString(input); | ||
result = MAPPER.readValue(json, DateTime.class); | ||
assertEquals("Actual timepoints differ", input.getMillis(), result.getMillis()); | ||
assertEquals("TimeZones differ", input, result); | ||
} | ||
|
||
/** | ||
* Test that de/serializing an ambiguous time (e.g. a 'fall back' DST transition) works and preserves the proper | ||
* instants in time and time zones. | ||
*/ | ||
public void testFallBackTransition() throws Exception | ||
{ | ||
DateTime firstOneAmUtc = new DateTime(FALL_BACK_YEAR, FALL_BACK_MONTH, FALL_BACK_DAY, FIRST_FALL_BACK_HOUR, 0, 0, | ||
DateTimeZone.UTC); | ||
DateTime secondOneAmUtc = new DateTime(FALL_BACK_YEAR, FALL_BACK_MONTH, FALL_BACK_DAY, SECOND_FALL_BACK_HOUR, 0, 0, | ||
DateTimeZone.UTC); | ||
|
||
DateTime firstOneAm = new DateTime(firstOneAmUtc, AMERICA_LOS_ANGELES); | ||
DateTime secondOneAm = new DateTime(secondOneAmUtc, AMERICA_LOS_ANGELES); | ||
|
||
ObjectWriter w = MAPPER.writer() | ||
.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
.with(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); | ||
|
||
String firstOneAmStr = w.writeValueAsString(firstOneAm); | ||
String secondOneAmStr = w.writeValueAsString(secondOneAm); | ||
|
||
DateTime firstRoundTrip = MAPPER.readValue(firstOneAmStr, DateTime.class); | ||
DateTime secondRoundTrip = MAPPER.readValue(secondOneAmStr, DateTime.class); | ||
|
||
assertEquals("Actual timepoints differ", firstOneAm.getMillis(), firstRoundTrip.getMillis()); | ||
assertEquals("TimeZones differ", firstOneAm, firstRoundTrip); | ||
|
||
assertEquals("Actual timepoints differ", secondOneAm.getMillis(), secondRoundTrip.getMillis()); | ||
assertEquals("TimeZones differ", secondOneAm, secondRoundTrip); | ||
} | ||
|
||
public void testSerializationWithTypeInfo() throws Exception | ||
{ | ||
// but if re-configured to include the time zone | ||
ObjectMapper m = jodaMapper(); | ||
m.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); | ||
m.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); | ||
|
||
m.addMixIn(DateTime.class, TypeInfoMixIn.class); | ||
assertEquals("[\"org.joda.time.DateTime\",\"0[UTC]\"]", | ||
m.writeValueAsString(DATE_JAN_1_1970_UTC)); | ||
} | ||
} |
This implementation differs from jsr310's: that one does not write the zone id in case timestamp serialization is used. Which approach is preferable? To me numbers with timezone look really odd, but maybe that is how it should be done and the feature should not be tied to string serialization.