Fixed [JACKSON-206], support for yet another iso-8601 date/time variation
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 71463f8..48149c5 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -36,6 +36,24 @@
== History: ==
------------------------------------------------------------------------
+1.3.1 [23-Nov-2009]
+
+ Fixes:
+
+ * [JACKSON-190] Problems deserializing certain nested generic types
+ (reported by Nathan C)
+ * [JACKSON-194] ObjectMapper class loading issues on Android
+ (reported by Martin L)
+ * [JACKSON-197] Remove 2 debug messages that print out to System.err
+ (reported by Edward T)
+ * [JACKSON-200] java.sql.Date deserialization not working well
+ (reported by Steve L)
+ * [JACKSON-202] Non-public fields not deserialized properly with
+ JAXB annotations
+ (reported by Mike P)
+ * [JACKSON-203] Date deserializers should map empty String to null
+ (reported by Steve L)
+
1.3.0 [30-Oct-2009]
Fixes:
diff --git a/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java b/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java
index 689dcad..0f1728e 100644
--- a/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java
+++ b/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java
@@ -17,6 +17,11 @@
public class StdDateFormat
extends DateFormat
{
+ /* TODO !!! 24-Nov-2009, tatu: Need to rewrite this class soon:
+ * JDK date parsing is awfully brittle, and ISO-8601 is quite
+ * permissive. The two don't mix, need to write a better one.
+ */
+
/**
* Defines a commonly used date format that conforms
* to ISO-8601 date formatting standard, when it includes basic undecorated
@@ -244,21 +249,40 @@
df = _formatISO8601_z = (SimpleDateFormat) DATE_FORMAT_ISO8601_Z.clone();
}
} else {
- c = dateStr.charAt(len-3);
- if (c == ':') { // remove optional colon
- // remove colon
- StringBuilder sb = new StringBuilder(dateStr);
- sb.delete(len-3, len-2);
- dateStr = sb.toString();
- } else if (c == '+' || c == '-') { // missing minutes
- // let's just append '00'
- dateStr += "00";
- }
- // otherwise regular (or invalid)
+ // Let's see if we have timezone indicator or not...
+ if (hasTimeZone(dateStr)) {
+ c = dateStr.charAt(len-3);
+ if (c == ':') { // remove optional colon
+ // remove colon
+ StringBuilder sb = new StringBuilder(dateStr);
+ sb.delete(len-3, len-2);
+ dateStr = sb.toString();
+ } else if (c == '+' || c == '-') { // missing minutes
+ // let's just append '00'
+ dateStr += "00";
+ }
+ df = _formatISO8601;
+ if (_formatISO8601 == null) {
+ df = _formatISO8601 = (SimpleDateFormat) DATE_FORMAT_ISO8601.clone();
+ }
+ } else {
+ /* 24-Nov-2009, tatu: Ugh. This is getting pretty
+ * ugly. Need to rewrite soon!
+ */
- df = _formatISO8601;
- if (_formatISO8601 == null) {
- df = _formatISO8601 = (SimpleDateFormat) DATE_FORMAT_ISO8601.clone();
+ // If not, plain date. Easiest to just patch 'Z' in the end?
+ StringBuilder sb = new StringBuilder(dateStr);
+ // And possible also millisecond part if missing
+ int timeLen = len - dateStr.lastIndexOf('T') - 1;
+ if (timeLen <= 8) {
+ sb.append(".000");
+ }
+ sb.append('Z');
+ dateStr = sb.toString();
+ df = _formatISO8601_z;
+ if (df == null) {
+ df = _formatISO8601_z = (SimpleDateFormat) DATE_FORMAT_ISO8601_Z.clone();
+ }
}
}
return df.parse(dateStr, pos);
@@ -271,5 +295,20 @@
}
return _formatRFC1123.parse(dateStr, pos);
}
+
+ private final static boolean hasTimeZone(String str)
+ {
+ // Only accept "+hh", "+hhmm" and "+hh:mm" (and with minus), so
+ int len = str.length();
+ if (len >= 6) {
+ char c = str.charAt(len-6);
+ if (c == '+' || c == '-') return true;
+ c = str.charAt(len-5);
+ if (c == '+' || c == '-') return true;
+ c = str.charAt(len-3);
+ if (c == '+' || c == '-') return true;
+ }
+ return false;
+ }
}
diff --git a/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java b/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java
index e160c9b..fca8d9a 100644
--- a/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java
+++ b/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java
@@ -77,14 +77,6 @@
assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH));
assertEquals(28, c.get(Calendar.DAY_OF_MONTH));
- // And finally, plain date (no time)
- inputStr = "1972-12-28";
- inputDate = mapper.readValue(quote(inputStr), java.util.Date.class);
- c.setTime(inputDate);
- assertEquals(1972, c.get(Calendar.YEAR));
- assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH));
- assertEquals(28, c.get(Calendar.DAY_OF_MONTH));
-
inputStr = "1984-11-30T00:00:00.000Z";
inputDate = mapper.readValue(quote(inputStr), java.util.Date.class);
c.setTime(inputDate);
@@ -93,6 +85,38 @@
assertEquals(30, c.get(Calendar.DAY_OF_MONTH));
}
+ public void testDateUtilISO8601NoTimezone() throws Exception
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ // Timezone itself is optional as well...
+ String inputStr = "1984-11-13T00:00:09";
+ Date inputDate = mapper.readValue(quote(inputStr), java.util.Date.class);
+ Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ c.setTime(inputDate);
+ assertEquals(1984, c.get(Calendar.YEAR));
+ assertEquals(Calendar.NOVEMBER, c.get(Calendar.MONTH));
+ assertEquals(13, c.get(Calendar.DAY_OF_MONTH));
+ assertEquals(0, c.get(Calendar.HOUR_OF_DAY));
+ assertEquals(0, c.get(Calendar.MINUTE));
+ assertEquals(9, c.get(Calendar.SECOND));
+ assertEquals(0, c.get(Calendar.MILLISECOND));
+ }
+
+ public void testDateUtilISO8601JustDate() throws Exception
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ // Plain date (no time)
+ String inputStr = "1972-12-28";
+ Date inputDate = mapper.readValue(quote(inputStr), java.util.Date.class);
+ Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ c.setTime(inputDate);
+ assertEquals(1972, c.get(Calendar.YEAR));
+ assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH));
+ assertEquals(28, c.get(Calendar.DAY_OF_MONTH));
+
+ }
+
+
@SuppressWarnings("deprecation")
public void testDateSql() throws Exception
{