javaxmldategregorian-calendarxmlgregoriancalendar

Why GregorianCalendar randomly add "Z" at the end of date and sometimes don't


I had to get the current date, add 20 years, and transferred it in an XML object.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "XMLCommande", propOrder = {
    ...
    "dateLivSouhaitee",
   ...
})
public class XMLCommande {
   ...
   @XmlElement(name = "date_liv_souhaitee", required = true)
   @XmlSchemaType(name = "date")
   protected XMLGregorianCalendar dateLivSouhaitee;
   ...
}

No date format is specified, it's all by default :

XMLCommande xmlMessage = new XMLCommande(); 

GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.add(Calendar.YEAR, 20);
ligne.setDateLivSouhaitee(DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar2));

The problem, is, for some unknown reason, that's sometimes I have a "Z" at the end of the date, but sometimes don't :

<date_liv_souhaitee>2041-05-26Z</date_liv_souhaitee>
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>

It's the same server, why sometimes I have the Z with "+02:00" and sometimes don't ? How can I force the format to be always :

<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>

Solution

  • Why do I sometimes get the Z and sometimes +02:00?

    If both come from creating a GregorianCalendar using the no-arg constructor and converting it to XMLGregorianCalendar, then the best explanation is that someone is modifying the default time zone of your JVM. A part of your own program may do that or some other program running in the same JVM. To demonstrate:

        TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Europe/Paris")));
        GregorianCalendar gc = new GregorianCalendar();
        System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
        
        TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC));
        gc = new GregorianCalendar();
        System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
    

    Output from these code lines was:

    2021-05-26T19:41:29.744+02:00
    2021-05-26T17:41:29.776Z
    

    new GregorianCalendar() creates a GregorianCalendar that has the default time zone of the JVM at the time of creation. As Arvind Kumar Avinash already explained, offset 0 from UTC is rendered as Z in accordance with the ISO 8601 standard.

    How can I force +02:00 always?

    I recommend that you use java.time, the modern Java date and time API, for your date work. The OffsetDateTime class represents a date and time with a UTC offset, so just set the offset to +2.

        OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(2));
        OffsetDateTime in20Years = now.plusYears(20);
        String dateStringWithOffset0200 = in20Years.format(DateTimeFormatter.ISO_OFFSET_DATE);
        System.out.println(dateStringWithOffset0200);
    

    2041-05-26+02:00

    If you do need an XMLGregorianCalendar, build one from the string we just got:

        XMLGregorianCalendar xmlgc = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(dateStringWithOffset0200);
        System.out.println(xmlgc);
    

    2041-05-26+02:00

    Links