Here is an ObjectStringConverter implementation that will convert java.util.Date into the ISO 8601 format used in the XML Schema Definition types xsd:dateTime, xsd:date, and xsd:time, depending on the specified flavour.
import java.text.*; import java.util.*; import org.apache.commons.betwixt.expression.*; import org.apache.commons.betwixt.strategy.*; /** * @author Jesse Sweetland */ public class DateObjectStringConverter extends ObjectStringConverter { private static final DateFormat PSUEDO_ISO8601_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); private static final DateFormat PSUEDO_ISO8601_DATETIME_FORMAT_TZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); private static final DateFormat PSUEDO_ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private static final DateFormat PSUEDO_ISO8601_DATE_FORMAT_TZ = new SimpleDateFormat("yyyy-MM-ddZ"); private static final DateFormat PSUEDO_ISO8601_TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); private static final DateFormat PSUEDO_ISO8601_TIME_FORMAT_TZ = new SimpleDateFormat("HH:mm:ssZ"); protected String getFlavor(Context context) { return context.getOptions().getValue(FLAVOUR_OPTION_NAME); } public String objectToString(Object object, Class type, Context context) { String flavor = getFlavor(context); if("xsd:date".equals(flavor)){ return toIso8601Date((Date)object); } else if("xsd:time".equals(flavor)){ return toIso8601Time((Date)object); } else { // Assume xsd:dateTime if not specified return toIso8601DateTime((Date)object); } } public Object stringToObject(String value, Class type, Context context) { String flavor = getFlavor(context); if("xsd:date".equals(flavor)){ return fromIso8601Date(value); } else if("xsd:time".equals(flavor)){ return fromIso8601Time(value); } else { // Assume xsd:dateTime if not specified return fromIso8601DateTime(value); } } private String toIso8601DateTime(Date dateTime) { if(dateTime == null) return null; StringBuilder psuedoIso8601DateTime = new StringBuilder(PSUEDO_ISO8601_DATETIME_FORMAT_TZ.format(dateTime)); String iso8601DateTime = psuedoIso8601DateTime.insert(psuedoIso8601DateTime.length() - 2, ':').toString(); return iso8601DateTime; } private String toIso8601Date(Date date) { if(date == null) return null; StringBuilder psuedoIso8601Date = new StringBuilder(PSUEDO_ISO8601_DATE_FORMAT_TZ.format(date)); String iso8601Date = psuedoIso8601Date.insert(psuedoIso8601Date.length() - 2, ':').toString(); return iso8601Date; } private String toIso8601Time(Date time) { if(time == null) return null; StringBuilder psuedoIso8601Time = new StringBuilder(PSUEDO_ISO8601_TIME_FORMAT_TZ.format(time)); String iso8601Time = psuedoIso8601Time.insert(psuedoIso8601Time.length() - 2, ':').toString(); return iso8601Time; } private Date fromIso8601DateTime(String iso8601DateTime) { if(iso8601DateTime == null) return null; try { iso8601DateTime = iso8601DateTime.trim(); boolean tzPresent = iso8601DateTime.length() > 19; if(tzPresent) { String psuedoIso8601DateTime; if(iso8601DateTime.charAt(19) == 'Z') { psuedoIso8601DateTime = new StringBuilder(iso8601DateTime.substring(0, 19)).append("-0000").toString(); } else { psuedoIso8601DateTime = new StringBuilder(iso8601DateTime).deleteCharAt(22).toString(); } return PSUEDO_ISO8601_DATETIME_FORMAT_TZ.parse(psuedoIso8601DateTime); } else { return PSUEDO_ISO8601_DATETIME_FORMAT.parse(iso8601DateTime); } } catch(Throwable t) { throw new IllegalArgumentException(t); } } private Date fromIso8601Date(String iso8601Date) { if(iso8601Date == null) return null; try { iso8601Date = iso8601Date.trim(); boolean tzPresent = iso8601Date.length() > 10; if(tzPresent) { String psuedoIso8601Date; if(iso8601Date.charAt(10) == 'Z') { psuedoIso8601Date = new StringBuilder(iso8601Date.substring(0, 10)).append("-0000").toString(); } else { psuedoIso8601Date = new StringBuilder(iso8601Date).deleteCharAt(13).toString(); } return PSUEDO_ISO8601_DATE_FORMAT_TZ.parse(psuedoIso8601Date); } else { return PSUEDO_ISO8601_DATE_FORMAT.parse(iso8601Date); } } catch(Throwable t) { throw new IllegalArgumentException(t); } } private Date fromIso8601Time(String iso8601Time) { if(iso8601Time == null) return null; try { iso8601Time = iso8601Time.trim(); boolean tzPresent = iso8601Time.length() > 8; if(tzPresent) { String psuedoIso8601Time; if(iso8601Time.charAt(8) == 'Z') { psuedoIso8601Time = new StringBuilder(iso8601Time.substring(0, 8)).append("-0000").toString(); } else { psuedoIso8601Time = new StringBuilder(iso8601Time).deleteCharAt(11).toString(); } return PSUEDO_ISO8601_TIME_FORMAT_TZ.parse(psuedoIso8601Time); } else { return PSUEDO_ISO8601_TIME_FORMAT.parse(iso8601Time); } } catch(Throwable t) { throw new IllegalArgumentException(t); } } public static void main(String[] args) { DateObjectStringConverter dosc = new DateObjectStringConverter(); Date now = new Date(); System.out.println(now + " => " + dosc.toIso8601DateTime(now)); System.out.println(now + " => " + dosc.toIso8601Date(now)); System.out.println(now + " => " + dosc.toIso8601Time(now)); String dateTime = "2006-08-09T13:26:50"; System.out.println(dateTime + " => " + dosc.fromIso8601DateTime(dateTime)); String dateTimeTz = "2006-08-09T13:26:50-05:00"; System.out.println(dateTimeTz + " => " + dosc.fromIso8601DateTime(dateTimeTz)); String dateTimeUtc = "2006-08-09T13:26:50Z"; System.out.println(dateTimeUtc + " => " + dosc.fromIso8601DateTime(dateTimeUtc)); String date = "2006-08-09"; System.out.println(date + " => " + dosc.fromIso8601Date(date)); String dateTz = "2006-08-09-05:00"; System.out.println(date + " => " + dosc.fromIso8601Date(dateTz)); String dateUtc = "2006-08-09Z"; System.out.println(date + " => " + dosc.fromIso8601Date(dateUtc)); String time = "13:26:50"; System.out.println(time + " => " + dosc.fromIso8601Time(time)); String timeTz = "13:26:50-05:00"; System.out.println(timeTz + " => " + dosc.fromIso8601Time(timeTz)); String timeUtc = "13:26:50Z"; System.out.println(timeUtc + " => " + dosc.fromIso8601Time(timeUtc)); } }
The .betwixt mapping documents will look something like this:
<?xml version="1.0"?> <info> <element name="myElement"> <element name="dateTime" property="dateTime"> <option> <name>org.apache.commons.betwixt.flavour</name> <value>xsd:dateTime</value> </option> </element> <element name="date" property="date"> <option> <name>org.apache.commons.betwixt.flavour</name> <value>xsd:date</value> </option> </element> <element name="time" property="time"> <option> <name>org.apache.commons.betwixt.flavour</name> <value>xsd:time</value> </option> </element> </element> </info>
Note that if no flavor is specified, it defaults to dateTime format. Also, when writing dates, the timezone is always specified (which is highly recommended).