Search code examples
javadateleading-zeroxmlgregoriancalendar

Xmlgregoriancalendar not allowed leading zero in ddMMyyyy


I tried to get XMLGregorianCalendar with date format ddMMyyy. When I tried to convert it from Date, it kept throwing me:

java.lang.IllegalArgumentException: Leading zeros are not allowed.

Is there anyway to fix it?

Thanks!

DateFormat format = new SimpleDateFormat("ddMMyyyy");
XMLGregorianCalendar gTest = DatatypeFactory.newInstance().newXMLGregorianCalendar(format.format(new Date(1, 9, 2018)));

Solution

  • First, you shouldn’t use the Date class if you can avoid it. You may also want to avoid XMLGregorianCalendar. Date and SimpleDateFormat are long outdated, and the latter in particular renowned for being troublesome. Today we have so much better in java.time, the modern Java date and time API. It may also sometimes replace XMLGregorianCalendar.

    But taking your word for it, you’ve got an old-fashioned Date object — maybe from a legacy API that you cannot change or don’t want to change just now. You need to convert it to an XMLGregorianCalendar. I still prefer to use java.time for the conversion.

        Date oldfashionedDate = // some Date equal to 1 August 2018 at 00:00 in my time zone;
        LocalDate modernDate = oldfashionedDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        XMLGregorianCalendar gTest = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(modernDate.toString());
        System.out.println(gTest);
    

    This prints:

    2018-08-01

    You asked for format ddMMyyyy. You cannot have that. Or more precisely, the only way you can have that is in a string, not in an XMLGregorianCalendar. XMLGregorianCalendar.toString() produces XML format, and this is defined in the XML Schema (see the link at the bottom). It goes like for example 2018-08-01, 2018-08-01T00:00:00 or 2018-08-01T00:00:00+02:00.

    What went wrong in your code?

    I could not reproduce your IllegalArgumentException. On my Java 10 the leading 0 of 01082018 was accepted (on Java 8 too). However, the data type factory parsed the string into a year of 1082018 (more than a million years from now), and since the string ended there, it didn’t parse any month or day of month. So the resulting XMLGregorianCalendar had only a year in it, no other fields were defined.

    newXMLGregorianCalendar(String) accepts only XML format. Apparently a year alone is accepted. The format still follows the specification linked to at the bottom of this answer.

    Accepting the leading 0 is probably a bug, though, since the leading zero is not printed back from the toXMLFormat method, which was supposed to give the same string back as was parsed, according to the documentation of newXMLGregorianCalendar(String).

    Links