Skip to content

Commit

Permalink
Fix #1657 (I hope)
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jun 14, 2017
1 parent fe80e86 commit 5a0ce57
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
6 changes: 6 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Project: jackson-databind
=== Releases ===
------------------------------------------------------------------------

2.8.9.1 (not yet released)

#1657: `StdDateFormat` deserializes dates with no tz/offset as UTC instead of
configured timezone
(reported by Bertrand R)

2.8.9 (12-Jun-2017)

#1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public class StdDateFormat
*/
protected final static String DATE_FORMAT_STR_ISO8601_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

/**
* Same as 'regular' 8601 except misses timezone altogether
*
* @since 2.8.10
*/
protected final static String DATE_FORMAT_STR_ISO8601_NO_TZ = "yyyy-MM-dd'T'HH:mm:ss.SSS";

/**
* ISO-8601 with just the Date part, no time
*/
Expand All @@ -56,6 +63,7 @@ public class StdDateFormat
protected final static String[] ALL_FORMATS = new String[] {
DATE_FORMAT_STR_ISO8601,
DATE_FORMAT_STR_ISO8601_Z,
DATE_FORMAT_STR_ISO8601_NO_TZ,
DATE_FORMAT_STR_RFC1123,
DATE_FORMAT_STR_PLAIN
};
Expand All @@ -70,11 +78,12 @@ public class StdDateFormat
}

private final static Locale DEFAULT_LOCALE = Locale.US;

protected final static DateFormat DATE_FORMAT_RFC1123;

protected final static DateFormat DATE_FORMAT_ISO8601;
protected final static DateFormat DATE_FORMAT_ISO8601_Z;
protected final static DateFormat DATE_FORMAT_ISO8601_NO_TZ; // since 2.8.10

protected final static DateFormat DATE_FORMAT_PLAIN;

Expand All @@ -93,6 +102,8 @@ public class StdDateFormat
DATE_FORMAT_ISO8601.setTimeZone(DEFAULT_TIMEZONE);
DATE_FORMAT_ISO8601_Z = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601_Z, DEFAULT_LOCALE);
DATE_FORMAT_ISO8601_Z.setTimeZone(DEFAULT_TIMEZONE);
DATE_FORMAT_ISO8601_NO_TZ = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601_NO_TZ, DEFAULT_LOCALE);
DATE_FORMAT_ISO8601_NO_TZ.setTimeZone(DEFAULT_TIMEZONE);
DATE_FORMAT_PLAIN = new SimpleDateFormat(DATE_FORMAT_STR_PLAIN, DEFAULT_LOCALE);
DATE_FORMAT_PLAIN.setTimeZone(DEFAULT_TIMEZONE);
}
Expand Down Expand Up @@ -123,6 +134,7 @@ public class StdDateFormat
protected transient DateFormat _formatRFC1123;
protected transient DateFormat _formatISO8601;
protected transient DateFormat _formatISO8601_z;
protected transient DateFormat _formatISO8601_noTz; // 2.8.10
protected transient DateFormat _formatPlain;

/*
Expand Down Expand Up @@ -504,11 +516,11 @@ protected Date parseAsISO8601(String dateStr, ParsePosition pos, boolean throwEr
_timezone, _locale, _lenient);
}
} else {
// If not, plain date. Easiest to just patch 'Z' in the end?
StringBuilder sb = new StringBuilder(dateStr);
// And possible also millisecond part if missing
// If not, plain date, no timezone
int timeLen = len - dateStr.lastIndexOf('T') - 1;
// And possible also millisecond part if missing
if (timeLen < 12) { // missing, or partial
StringBuilder sb = new StringBuilder(dateStr);
switch (timeLen) {
case 11: sb.append('0');
case 10: sb.append('0');
Expand All @@ -517,17 +529,16 @@ protected Date parseAsISO8601(String dateStr, ParsePosition pos, boolean throwEr
default:
sb.append(".000");
}
dateStr = sb.toString();
}
sb.append('Z');
dateStr = sb.toString();
df = _formatISO8601_z;
formatStr = DATE_FORMAT_STR_ISO8601_Z;
df = _formatISO8601_noTz;
formatStr = DATE_FORMAT_STR_ISO8601_NO_TZ;
if (df == null) {
// 10-Jun-2017, tatu: As per [databind#1651], when using this format,
// must use UTC, not whatever is configured as default timezone
// (because we know `Z` identifier is used)
df = _formatISO8601_z = _cloneFormat(DATE_FORMAT_ISO8601_Z, formatStr,
DEFAULT_TIMEZONE, _locale, _lenient);
df = _formatISO8601_noTz = _cloneFormat(DATE_FORMAT_ISO8601_NO_TZ, formatStr,
_timezone, _locale, _lenient);
}
}
}
Expand Down Expand Up @@ -588,6 +599,8 @@ protected void _clearFormats() {
_formatRFC1123 = null;
_formatISO8601 = null;
_formatISO8601_z = null;
_formatISO8601_noTz = null;

_formatPlain = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,28 @@ public void testDateUtilISO8601NoTimezone() throws Exception
assertEquals(0, c.get(Calendar.MILLISECOND));
}

// [databind#1657]: no timezone should use configured default
public void testDateUtilISO8601NoTimezoneNonDefault() throws Exception
{
// In first case, no timezone -> SHOULD use configured timezone
ObjectReader r = MAPPER.readerFor(Date.class);
TimeZone tz = TimeZone.getTimeZone("GMT-2");
Date date1 = r.with(tz)
.readValue(quote("1970-01-01T00:00:00.000"));
// Second case, should use specified timezone, not configured
Date date2 = r.with(TimeZone.getTimeZone("GMT+5"))
.readValue(quote("1970-01-01T00:00:00.000-02:00"));
assertEquals(date1, date2);

// also verify actual value, in GMT
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
c.setTime(date1);
assertEquals(1970, c.get(Calendar.YEAR));
assertEquals(Calendar.JANUARY, c.get(Calendar.MONTH));
assertEquals(1, c.get(Calendar.DAY_OF_MONTH));
assertEquals(2, c.get(Calendar.HOUR_OF_DAY));
}

// [Issue#338]
public void testDateUtilISO8601NoMilliseconds() throws Exception
{
Expand Down Expand Up @@ -296,7 +318,7 @@ public void testDateUtilISO8601NoMilliseconds() throws Exception
assertEquals(0, c.get(Calendar.MILLISECOND));
*/
}

public void testDateUtilISO8601JustDate() throws Exception
{
// Plain date (no time)
Expand Down

0 comments on commit 5a0ce57

Please sign in to comment.