Skip to content

Commit

Permalink
Fix #83
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jul 1, 2016
1 parent 6f69605 commit dd4a8e7
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 18 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project: jackson-datatype-joda

2.8.0 (not yet released)

#83: WRITE_DATES_WITH_ZONE_ID feature not working when applied on @JsonFormat annotation
(reported by mandyWW@github)
#87: Add support for JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE
(contributed by Alexey B)
- Support "config overrides" for `@JsonFormat.Value` added in databind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;

/**
Expand All @@ -27,8 +29,20 @@ public class JacksonJodaDateFormat extends JacksonJodaFormatBase

protected final boolean _explicitTimezone;

/**
* Flag for <code>JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE</code>
*
* @since 2.8
*/
protected final Boolean _adjustToContextTZOverride;

/**
* Flag for <code>JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID</code>
*
* @since 2.8
*/
protected final Boolean _writeZoneId;

public JacksonJodaDateFormat(DateTimeFormatter defaultFormatter)
{
super();
Expand All @@ -37,16 +51,29 @@ public JacksonJodaDateFormat(DateTimeFormatter defaultFormatter)
_jdkTimezone = (tz == null) ? null : tz.toTimeZone();
_explicitTimezone = false;
_adjustToContextTZOverride = null;
_writeZoneId = null;
}

public JacksonJodaDateFormat(JacksonJodaDateFormat base,
Boolean useTimestamp, Boolean adjustToContextTZOverride)
Boolean useTimestamp)
{
super(base, useTimestamp);
_formatter = base._formatter;
_jdkTimezone = base._jdkTimezone;
_explicitTimezone = base._explicitTimezone;
_adjustToContextTZOverride = base._adjustToContextTZOverride;
_writeZoneId = base._writeZoneId;
}

public JacksonJodaDateFormat(JacksonJodaDateFormat base,
Boolean adjustToContextTZOverride, Boolean writeZoneId)
{
super(base);
_formatter = base._formatter;
_jdkTimezone = base._jdkTimezone;
_explicitTimezone = base._explicitTimezone;
_adjustToContextTZOverride = adjustToContextTZOverride;
_writeZoneId = writeZoneId;
}

public JacksonJodaDateFormat(JacksonJodaDateFormat base,
Expand All @@ -57,6 +84,7 @@ public JacksonJodaDateFormat(JacksonJodaDateFormat base,
_jdkTimezone = base._jdkTimezone;
_explicitTimezone = base._explicitTimezone;
_adjustToContextTZOverride = base._adjustToContextTZOverride;
_writeZoneId = base._writeZoneId;
}

public JacksonJodaDateFormat(JacksonJodaDateFormat base, TimeZone jdkTimezone)
Expand All @@ -66,6 +94,7 @@ public JacksonJodaDateFormat(JacksonJodaDateFormat base, TimeZone jdkTimezone)
_jdkTimezone = jdkTimezone;
_explicitTimezone = true;
_adjustToContextTZOverride = base._adjustToContextTZOverride;
_writeZoneId = base._writeZoneId;
}

public JacksonJodaDateFormat(JacksonJodaDateFormat base, Locale locale)
Expand All @@ -75,6 +104,7 @@ public JacksonJodaDateFormat(JacksonJodaDateFormat base, Locale locale)
_jdkTimezone = base._jdkTimezone;
_explicitTimezone = base._explicitTimezone;
_adjustToContextTZOverride = base._adjustToContextTZOverride;
_writeZoneId = base._writeZoneId;
}

/*
Expand All @@ -83,11 +113,25 @@ public JacksonJodaDateFormat(JacksonJodaDateFormat base, Locale locale)
/**********************************************************
*/

public JacksonJodaDateFormat with(JsonFormat.Value ann) {
JacksonJodaDateFormat format = this;
format = format.withLocale(ann.getLocale());
format = format.withTimeZone(ann.getTimeZone());
format = format.withFormat(ann.getPattern().trim());
Boolean adjustTZ = ann.getFeature(JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
Boolean writeZoneId = ann.getFeature(JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID);
if ((adjustTZ != _adjustToContextTZOverride)
|| (writeZoneId != _writeZoneId)) {
format = new JacksonJodaDateFormat(format, adjustTZ, writeZoneId);
}
return format;
}

public JacksonJodaDateFormat withUseTimestamp(Boolean useTimestamp) {
if ((_useTimestamp != null) && _useTimestamp.equals(useTimestamp)) {
return this;
}
return new JacksonJodaDateFormat(this, useTimestamp, _adjustToContextTZOverride);
return new JacksonJodaDateFormat(this, useTimestamp);
}

public JacksonJodaDateFormat withFormat(String format) {
Expand Down Expand Up @@ -121,12 +165,26 @@ public JacksonJodaDateFormat withLocale(Locale locale) {
return new JacksonJodaDateFormat(this, locale);
}

/**
* @since 2.8
*/
public JacksonJodaDateFormat withAdjustToContextTZOverride(Boolean adjustToContextTZOverride) {
// minor efficiency check to avoid recreation if no change:
if (adjustToContextTZOverride == _adjustToContextTZOverride) {
return this;
}
return new JacksonJodaDateFormat(this, _useTimestamp, adjustToContextTZOverride);
return new JacksonJodaDateFormat(this, adjustToContextTZOverride, _writeZoneId);
}

/**
* @since 2.8
*/
public JacksonJodaDateFormat withWriteZoneId(Boolean writeZoneId) {
// minor efficiency check to avoid recreation if no change:
if (writeZoneId == _writeZoneId) {
return this;
}
return new JacksonJodaDateFormat(this, _adjustToContextTZOverride, writeZoneId);
}

/*
Expand Down Expand Up @@ -201,7 +259,7 @@ public DateTimeFormatter createParser(DeserializationContext ctxt)
}
}
if (!_explicitTimezone) {
if (isAdjustDatesToContextTimeZone(ctxt)) {
if (shouldAdjustToContextTimeZone(ctxt)) {
TimeZone tz = ctxt.getTimeZone();
if (tz != null && !tz.equals(_jdkTimezone)) {
formatter = formatter.withZone(DateTimeZone.forTimeZone(tz));
Expand All @@ -213,9 +271,20 @@ public DateTimeFormatter createParser(DeserializationContext ctxt)
return formatter;
}

private boolean isAdjustDatesToContextTimeZone(DeserializationContext ctxt) {
return (_adjustToContextTZOverride != null) ? _adjustToContextTZOverride :
ctxt.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
/**
* @since 2.8
*/
public boolean shouldAdjustToContextTimeZone(DeserializationContext ctxt) {
return (_adjustToContextTZOverride != null) ? _adjustToContextTZOverride :
ctxt.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}

/**
* @since 2.8
*/
public boolean shouldWriteWithZoneId(SerializerProvider ctxt) {
return (_writeZoneId != null) ? _writeZoneId :
ctxt.isEnabled(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
format = format.withUseTimestamp(useTimestamp);
}
// for others, safe to call, null/empty just ignored
format = format.withFormat(ann.getPattern().trim());
format = format.withLocale(ann.getLocale());
format = format.withTimeZone(ann.getTimeZone());
format = format.withAdjustToContextTZOverride(
ann.getFeature(JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE));
format = format.with(ann);
if (format != _format) {
return withFormat(format);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public boolean isEmpty(SerializerProvider prov, DateTime value) {
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException
{
// First: simple, non-timezone-included output
if (!provider.isEnabled(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)) {
if (!writeWithZoneId(provider)) {
if (_useTimestamp(provider)) {
gen.writeNumber(value.getMillis());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,7 @@ public JsonSerializer<?> createContextual(SerializerProvider prov,
if (useTimestamp != null) {
format = format.withUseTimestamp(useTimestamp);
}
// for others, safe to call, null/empty just ignored
format = format.withFormat(ann.getPattern().trim());
format = format.withLocale(ann.getLocale());
format = format.withTimeZone(ann.getTimeZone());
format = format.with(ann);
if (format != _format) {
return withFormat(format);
}
Expand Down Expand Up @@ -125,4 +122,11 @@ protected void _acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaTy
protected boolean _useTimestamp(SerializerProvider provider) {
return _format.useTimestamp(provider, _featureForNumeric);
}

/**
* @since 2.8
*/
protected boolean writeWithZoneId(SerializerProvider provider) {
return _format.shouldWriteWithZoneId(provider);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.fasterxml.jackson.datatype.joda;
package com.fasterxml.jackson.datatype.joda.ser;

import java.io.IOException;
import java.text.SimpleDateFormat;
Expand All @@ -11,6 +11,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaTestBase;

public class JodaSerializationTest extends JodaTestBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.fasterxml.jackson.datatype.joda.ser;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaTestBase;

public class WriteZoneIdTest extends JodaTestBase
{
static class DummyClassWithDate {
@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss Z",
with = JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID)
public DateTime date;

DummyClassWithDate() { }

public DummyClassWithDate(DateTime date) {
this.date = date;
}
}

public void testJacksonAnnotatedPOJOWithDateWithTimezoneToJson() throws Exception
{
ObjectMapper mapper = jodaMapper();
String ZONE_ID = "Asia/Krasnoyarsk";

DummyClassWithDate input = new DummyClassWithDate(new DateTime(2015, 11, 23, 22, 06, 39,
DateTimeZone.forID(ZONE_ID)));
// 30-Jun-2016, tatu: Exact time seems to vary a bit based on DST, so let's actually
// just verify appending of timezone id itself:
String json = mapper.writeValueAsString(input);
if (!json.contains("\"23-11-2015")) {
fail("Should contain time prefix, did not: "+json);
}
String match = String.format("[%s]", ZONE_ID);
if (!json.contains(match)) {
fail("Should contain zone id "+match+", does not: "+json);
}
}
}

0 comments on commit dd4a8e7

Please sign in to comment.