Fetching Date from XMLGregorianCalendar

2019-08-28 04:51发布

问题:

I have been working on task where I need to fetch Date from XMLGregorianCalendar.I have converted it to GregorianCalendar and tried to get date from it.But I am seeing difference between original date stored in XMLGregorianCalendar and Date obtained from toGregorianCalendar, I want date to be in UTC format and source time zone is also in UTC.Please find code snippet for reference.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ";
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
String date = sdf.format(xmlGregorianCalendar.toGregorianCalendar().getTime());

I am wondering if there is any way to get Date from XMLGregorianCalendar with UTC time zone and without any time difference.Below is the sample source date stored in XMLGregorianCalendar

2018-07-06T05:11:00.050Z

I am expecting exact same date as string after I format it with SimpleDateFormat.Your help is much appreciated, thanks in advance!

回答1:

    OffsetDateTime dateTime = xmlGregorianCalendar.toGregorianCalendar()
            .toZonedDateTime()
            .toOffsetDateTime();
    System.out.println("Date-time with explicit offset: " + dateTime);
    System.out.println("Offset is " + dateTime.getOffset());

With your XMLGregorianCalendar this prints:

Date-time with explicit offset: 2018-07-06T05:11:00.050Z
Offset is Z

Z means UTC or offset zero or Zulu time zone. So this gives you date and time in UTC with explicit offset.

If what you really need is just the correct point in time, one would usually use an Instant for that:

    Instant pointInTime = xmlGregorianCalendar.toGregorianCalendar()
            .toZonedDateTime()
            .toInstant();
    System.out.println("As point in time: " + pointInTime);

Output:

As point in time: 2018-07-06T05:11:00.050Z

You notice that the date and time is printed exactly as before including the Z for UTC. The difference is: an OffsetDateTime may hold any offset (and will hold a different offset if your XMLGregorianCalendar does). An Instant is thought of as a point in time independent of any zone or offset. It is only its toString method that uses UTC for printing a date and time, and the suffix will always be Z for UTC.

What went wrong on your code?

First, the SimpleDateFormat class is not only long outdated. It is also notoriously troublesome, particularly when it comes to parsing, but still. TimeZone is outdated too. You will prefer to use java.time, the modern Java date and time API, as I am doing in the above snippets.

I ran your code and got 2018-07-06T05:11:00.050+0000. Offset zero from UTC is printed differently, but the string agrees with what you say you want.

You cannot have a java.util.Date (another outdated class) with a time zone or offset. It represents a point in time, nothing more.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • All about java.util.Date (entry on Jon Skeet’s coding blog)