java.util.Date to XMLGregorianCalendar
Asked Answered
A

10

658

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

Audiology answered 7/5, 2009 at 17:5 Comment(1)
FYI: Both of these terrible classes were supplanted years ago by the java.time classes defined in JSR 310. See ZonedDateTime class, and new conversion methods added to the legacy classes. Details in this Answer by Ole V.V.Melindamelinde
A
74

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

Auld answered 26/5, 2019 at 11:57 Comment(7)
Your answer is not really answer to the original question. Its fine and fun when you can choose between legacy and modern code. But if you come here with this question its not like you have the choice. Even your sample to convert is plain wrong, since it doesn't work in java 7 and below.Laureate
Thank you, @Nagh, for the criticism, appreciated. I admit I had estimated that most users would have the choice. For those (many or few) whose evil boss forces them to use Java 7, I recommend using java.time through the backport, ThreeTen Backport. You may of course also look at the many other answers. I still consider code that uses a feature from Java 8 or later correct, or most of the code I write in my work is plain wrong. You are correct: I believe more in writing helpful answer (at least to some) than direct answers to the questions as asked.Auld
I believe more in writing helpful answer (at least to some) than direct answers I would agree on that, however helpful answer must include direct answer to be really helpful. I still have to deal with Java 5 code, so feel my pain.Laureate
I feel your pain, @Nagh. If you have the choice, you may look into Joda-Time for any serious date and time work, it too produces ISO 8601 out of the box. When writing this answer one and a half years ago I saw no point in repeating the direct answer that many others had already given. Had it been missing, I agree, then I would have included it.Auld
Date is still being used a lot.Lambrequin
@Lambrequin Unfortunately you are correct. Thanks for confirming that I am not beating a dead horse when I recommend against it.Auld
@OleV.V. yes but your "answer" does not actually answer when someone needs Date->XML calendar unlike answer below.Lambrequin
R
1084
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
Rowell answered 7/5, 2009 at 17:22 Comment(12)
Is it save to keep the getInstance() as a static variable in some converter class? I tried to look it up in the JavaDoc but couldn't find anything. Kinda hard to know if there will be problems in concurrent usage?Apomict
If you are willing to use JodaTime you can do this in one line: DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar())Necrotomy
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar(YYYY, MM, DD));Weiler
Please be aware of that Calendar isn't threadsafe and therefore also GregorianCalender isn't. See also #12131824Ophthalmology
One line version - DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar() {{ setTime(yourDate); }})Twittery
How to do a dateFormat for XMLGregorianCalendar?Aphid
@AlexVayda Avoid double brace initializationAuld
FYI, the terribly troublesome date-time classes such as java.util.Date, java.util.Calendar, and XMLGregorianCalendar are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle.Melindamelinde
@BasilBourque the link about making java.util.* legacy is pointing to wikipedia, was it intended? How exactly does it apply to JAXB which steel seems to require XMLGregorianCalendar?Lindeman
@9ilsdx9rvj0lo Re: Wikipedia, yes, intended, to explain an idiom peculiar to computing. Re: Using java.time with JAXB, see this Answer with a link to GitHub for an implementation of an adapter.Melindamelinde
@BasilBourque Thanks for link. The issue still opened, it doesn't look like those classes will become real legacy soon... as much as we would wish it...Lindeman
@9ilsdx9rvj0lo Also, the alternatives to JAXB also have adapters to support java.time, such as Jackson and GSON.Melindamelinde
N
209

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();
Nicias answered 4/1, 2011 at 15:3 Comment(0)
A
74

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

Auld answered 26/5, 2019 at 11:57 Comment(7)
Your answer is not really answer to the original question. Its fine and fun when you can choose between legacy and modern code. But if you come here with this question its not like you have the choice. Even your sample to convert is plain wrong, since it doesn't work in java 7 and below.Laureate
Thank you, @Nagh, for the criticism, appreciated. I admit I had estimated that most users would have the choice. For those (many or few) whose evil boss forces them to use Java 7, I recommend using java.time through the backport, ThreeTen Backport. You may of course also look at the many other answers. I still consider code that uses a feature from Java 8 or later correct, or most of the code I write in my work is plain wrong. You are correct: I believe more in writing helpful answer (at least to some) than direct answers to the questions as asked.Auld
I believe more in writing helpful answer (at least to some) than direct answers I would agree on that, however helpful answer must include direct answer to be really helpful. I still have to deal with Java 5 code, so feel my pain.Laureate
I feel your pain, @Nagh. If you have the choice, you may look into Joda-Time for any serious date and time work, it too produces ISO 8601 out of the box. When writing this answer one and a half years ago I saw no point in repeating the direct answer that many others had already given. Had it been missing, I agree, then I would have included it.Auld
Date is still being used a lot.Lambrequin
@Lambrequin Unfortunately you are correct. Thanks for confirming that I am not beating a dead horse when I recommend against it.Auld
@OleV.V. yes but your "answer" does not actually answer when someone needs Date->XML calendar unlike answer below.Lambrequin
S
32

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 :-)

Sabadilla answered 7/5, 2009 at 17:26 Comment(1)
This a solution to convert GregorianCalendar to XMLGregorianCalendar and not what is indicated in the questionTractile
N
23

A one line example using Joda-Time library:

XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());

Credit to Nicolas Mommaerts from his comment in the accepted answer.

Nudi answered 3/2, 2014 at 14:35 Comment(0)
F
13

Just thought I'd add my solution below, since the answers above did not meet my exact needs. My Xml schema required seperate Date and Time elements, not a singe DateTime field. The standard XMLGregorianCalendar constructor used above will generate a DateTime field

Note there a couple of gothca's, such as having to add one to the month (since java counts months from 0).

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);
Fadge answered 16/3, 2011 at 13:2 Comment(0)
M
10

I hope my encoding here is right ;D To make it faster just use the ugly getInstance() call of GregorianCalendar instead of constructor call:

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 {
      // do not forget the type cast :/
      GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}
Masterwork answered 21/9, 2010 at 5:49 Comment(1)
-1 for using .getInstance(). GregorianCalendar.getInstance() is the equivalent of Calendar.getInstance(). The Calendar.getInstance() cannot make it faster, because it uses the same new GregorianCalendar(), but before it also checks the default locale and could create Japanese or Buddish calendar instead, so for some lucky users it will be ClassCastException!Headlight
S
8

Assuming you are decoding or encoding xml and using JAXB, then it's possible to replace the dateTime binding entirely and use something else than `XMLGregorianCalendar' for every date in the schema.

In that way you can have JAXB do the repetitive stuff while you can spend the time on writing awesome code that delivers value.

Example for a jodatime DateTime: (Doing this with java.util.Date would also work - but with certain limitations. I prefer jodatime and it's copied from my code so I know it works...)

<jxb:globalBindings>
    <jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
        parseMethod="test.util.JaxbConverter.parseDateTime"
        printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
    <jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
        parseMethod="test.util.JaxbConverter.parseDate"
        printMethod="test.util.JaxbConverter.printDate" />
    <jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
        parseMethod="test.util.JaxbConverter.parseTime"
        printMethod="test.util.JaxbConverter.printTime" />
    <jxb:serializable uid="2" />
</jxb:globalBindings>

And the converter:

public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();

public static LocalDateTime parseDateTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        LocalDateTime r = dtf.parseLocalDateTime(s);
        return r;
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDateTime(LocalDateTime d) {
    try {
        if (d == null)
            return null;
        return dtf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalDate parseDate(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalDate(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDate(LocalDate d) {
    try {
        if (d == null)
            return null;
        return df.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printTime(LocalTime d) {
    try {
        if (d == null)
            return null;
        return tf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalTime parseTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalTime(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

See here: how replace XmlGregorianCalendar by Date?

If you are happy to just map to an instant based on the timezone+timestamp, and the original timezone is not really relevant, then java.util.Date is probably fine too.

Sumba answered 22/4, 2013 at 10:0 Comment(0)
L
2

Check out this code :-

/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();

gc.setTime(date);

try{
    xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
    e.printStackTrace();
}

System.out.println("XMLGregorianCalendar :- " + xmlDate);

You can see complete example here

Liturgy answered 24/3, 2017 at 10:51 Comment(2)
I don't think that this answer provides nothing new.. Perhaps you can edit the previous answer instead of post another almost the same.Corissa
How to do a dateFormat for XMLGregorianCalendar?Aphid
K
-1

My solution

public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {

    GregorianCalendar gregoriancalendar = new GregorianCalendar();
    gregoriancalendar.setTime(date);
    XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar);
    return xmlGregorianCalendar;
}
Krauss answered 9/2, 2022 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.