java.util.Date to XMLGregorianCalendar

GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

For those that might end up here looking for the opposite conversion (from XMLGregorianCalendar to Date):

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();

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

  • Oracle tutorial: Date Time explaining how to use java.time.
  • XSD Date and Time Data Types on W3Schools.
  • Wikipedia article: ISO 8601

Here is a method for converting from a GregorianCalendar to XMLGregorianCalendar; I'll leave the part of converting from a java.util.Date to GregorianCalendar as an exercise for you:

import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      GregorianCalendar gcal = new GregorianCalendar();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

EDIT: Slooow :-)