Details
Description
The XML formatting for xsd:datetime does not appear to account properly for the serialization/deserialization if you force a timezone on marshalling/unmarshalling. The simple fix is one line of code missing in the DateFieldHandler class in the org.exolab.castor.xml.handlers package.
The following code I believe shows the problem.
package import org.exolab.castor.xml.handlers;
import java.util.TimeZone;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import org.exolab.castor.types.DateTime;
import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.xml.handlers.DateFieldHandler;
public class CastorTester {
public static void main(String args[]) {
try {
DateFieldHandler.setDefaultTimeZone(TimeZone.getTimeZone("UTC"));
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d1 = dateFormat.parse("01-01-2000 00:00:00");
dateFormat.setTimeZone(TimeZone.getTimeZone("CST"));
Date d2 = dateFormat.parse("01-01-2000 00:00:00");
System.out.println("D1: " + d1);
System.out.println("D2: " + d2);
DateTime date = new DateTime("2000-01-01T00:00:00.000Z");
Date d3 = new Date();
d3.setTime(date.toLong());
System.out.println("D3: " + d3);
Date d4 = DateFieldHandler.parse("2000-01-01T00:00:00.000Z");
System.out.print("D4: " + d4 + " ");
System.out.println(DateFieldHandler.format(d4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
What I expected was that parsing and formatting are inverses. However, if you run as-is you get: (default time zone is CST)
D1: Fri Dec 31 18:00:00 CST 1999
D2: Sat Jan 01 00:00:00 CST 2000
D3: Fri Dec 31 18:00:00 CST 1999
D4: Fri Dec 31 18:00:00 CST 1999 1999-12-31T18:00:00.000Z
I expected D4 to represent the same value parsed, 2000-01-01 0Z
However, if I call setTimeZone on the formatter in the format method (add 1 line of code) of DateFieldHandler (details below under MODIFIED CODE), I get my expected output for D4:
D1: Fri Dec 31 18:00:00 CST 1999
D2: Sat Jan 01 00:00:00 CST 2000
D3: Fri Dec 31 18:00:00 CST 1999
D4: Fri Dec 31 18:00:00 CST 1999 2000-01-01T00:00:00.000Z
I'm afraid I cannot change this. I expect to get back the same date from parsing and formatting.
NEW MODIFIED CODE:
/**
- Returns the given date in a String format, using the ISO8601 format as
- specified in the W3C XML Schema 1.0 Recommendation (Part 2: Datatypes)
- for dateTime.
* - @param date the Date to format
- @return the formatted string
*/
protected static String format(final Date date) {
final SimpleDateFormat formatter;
if (_suppressMillis) { formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); } else { formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); }
/* ensure the formatter does not use the default system timezone */
formatter.setTimeZone(_timezone);
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
cal.setTimeZone(_timezone);
StringBuffer buffer = new StringBuffer(DEFAULT_DATE_LENGTH);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
buffer.append("-");
}
buffer.append(formatter.format(date));
formatTimeZone(cal, buffer);
return buffer.toString();
} // – format
Initial patch (created from the code fragment given above).