Skip to content
Advertisement

java.util.Date to XMLGregorianCalendar

Isn’t there a convenient way of getting from a java.util.Date to a XMLGregorianCalendar?

Answer

I should like to take a step back and a modern look at this 10 years old question. The classes mentioned, Date and XMLGregorianCalendar, are old now. I challenge the use of them and offer alternatives.

  • Date was always poorly designed and is more than 20 years old. This is simple: don’t use it.
  • XMLGregorianCalendar is old too and has an old-fashioned design. As I understand it, it was used for producing dates and times in XML format for XML documents. Like 2009-05-07T19:05:45.678+02:00 or 2009-05-07T17:05:45.678Z. These formats agree well enough with ISO 8601 that the classes of java.time, the modern Java date and time API, can produce them, which we prefer.

No conversion necessary

For many (most?) purposes the modern replacement for a Date will be an Instant. An Instant is a point in time (just as a Date is).

    Instant yourInstant = // ...
    System.out.println(yourInstant);

An example output from this snippet:

2009-05-07T17:05:45.678Z

It’s the same as the latter of my example XMLGregorianCalendar strings above. As most of you know, it comes from Instant.toString being implicitly called by System.out.println. With java.time, in many cases we don’t need the conversions that in the old days we made between Date, Calendar, XMLGregorianCalendar and other classes (in some cases we do need conversions, though, I am showing you a couple in the next section).

Controlling the offset

Neither a Date nor in Instant has got a time zone nor a UTC offset. The previously accepted and still highest voted answer by Ben Noland uses the JVMs current default time zone for selecting the offset of the XMLGregorianCalendar. To include an offset in a modern object we use an OffsetDateTime. For example:

    ZoneId zone = ZoneId.of("America/Asuncion");
    OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
    System.out.println(dateTime);

2009-05-07T13:05:45.678-04:00

Again this conforms with XML format. If you want to use the current JVM time zone setting again, set zone to ZoneId.systemDefault().

What if I absolutely need an XMLGregorianCalendar?

There are more ways to convert Instant to XMLGregorianCalendar. I will present a couple, each with its pros and cons. First, just as an XMLGregorianCalendar produces a string like 2009-05-07T17:05:45.678Z, it can also be built from such a string:

    String dateTimeString = yourInstant.toString();
    XMLGregorianCalendar date2
            = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
    System.out.println(date2);

2009-05-07T17:05:45.678Z

Pro: it’s short and I don’t think it gives any surprises. Con: To me it feels like a waste formatting the instant into a string and parsing it back.

    ZonedDateTime dateTime = yourInstant.atZone(zone);
    GregorianCalendar c = GregorianCalendar.from(dateTime);
    XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
    System.out.println(date2);

2009-05-07T13:05:45.678-04:00

Pro: It’s the official conversion. Controlling the offset comes naturally. Con: It goes through more steps and is therefore longer.

What if we got a Date?

If you got an old-fashioned Date object from a legacy API that you cannot afford to change just now, convert it to Instant:

    Instant i = yourDate.toInstant();
    System.out.println(i);

Output is the same as before:

2009-05-07T17:05:45.678Z

If you want to control the offset, convert further to an OffsetDateTime in the same way as above.

If you’ve got an old-fashioned Date and absolutely need an old-fashioned XMLGregorianCalendar, just use the answer by Ben Noland.

Links

Advertisement