简体   繁体   中英

XMLGregorianCalendar date format 'dd/MM/yyyy HH:mm:ss.SSS'

String formatA ="yyyy-MM-dd'T'HH:mm:ss'Z'";
String formatB = "dd/MM/yyyy HH:mm:ss.SSS";
try {
    XMLGregorianCalendar gregFmt = DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat(formatB).format(new Date()));
    System.out.println(gregFmt);
} catch (DatatypeConfigurationException e) {
};

I am trying to formate XMLGregorianCalendar date . The above code formats well for format "yyyy-MM-dd'T'HH:mm:ss'Z'"

But for formatB dd/MM/yyyy HH:mm:ss.SSS it throws error

java.lang.IllegalArgumentException

Do advice on how to fix it. Thank you so much!

log

Exception in thread "main" java.lang.IllegalArgumentException: 23/08/2017 16:13:04.140
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parseAndSetYear(XMLGregorianCalendarImpl.java:2887)
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parse(XMLGregorianCalendarImpl.java:2773)
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl.<init>(XMLGregorianCalendarImpl.java:435)
at com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl.newXMLGregorianCalendar(DatatypeFactoryImpl.java:536)
at test.test.main(test.java:19)

line19 is line 4 , in the above code 'XMLGregorianCalendar gregFmt...'

XML规范中描述了newXMLGregorianCalendar(string)接受的格式,该格式不同于您尝试使用的formatB

tl;dr

  • Date-time objects do not have a “format”. They parse & generate String objects representing textually their value.
  • Use the modern java.time that replaced terrible old classes Date & XMLGregorianCalendar classes.

Example:

myXMLGregorianCalendar   // If you must use this class… but try to avoid. Use *java.time* classes instead.
.toGregorianCalendar()   // Converting from `javax.xml.datatype.XMLGregorianCalendar` to `java.util.GregorianCalendar`.
.toZonedDateTime()       // Converting from `java.util.GregorianCalendar` to `java.time.ZonedDateTime`, from legacy class to modern class.
.format(                 // Generate a `String` representing the moment stored in our `ZonedDateTime` object.
    DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss.SSS" )  // Define a formatting pattern as you desire. Or better, automatically localize by calling `DateTimeFormatter.ofLocalized…` methods.
)                        // Returns a `String` object, distinct from our `ZonedDateTime` object.

07/07/2018 15:20:14.372

Date-time objects do not have a format

Do not conflate date-time objects with the strings they generate to represent their value. Date-time values, including the classes discussed below, are not a String , do not use text as their internal value, and do not have a “format”. All of them can generate, and parse, strings to represent their date-time value.

java.time

The modern approach uses the java.time classes that supplanted the troublesome old legacy date-time classes such as XMLGregorianCalendar .

The use of java.util.Date should be replaced with java.time.Instant . Both represent a moment in UTC. Instant uses a finer resolution of nanoseconds rather than milliseconds.

You can easily convert between the modern and legacy classes. Notice the new conversion methods added to the old classes, in this case java.util.GregorianCalendar::toZonedDateTime .

First convert from javax.xml.datatype.XMLGregorianCalendar to java.util.GregorianCalendar .

GregorianCalendar gc = myXMLGregorianCalendar.toGregorianCalendar() ;

Now get out of these legacy classes, and into java.time.

ZonedDateTime zdt = gc.toZonedDateTime() ;

All three types so far, the XMLGregorianCalendar , the GregorianCalendar , and the ZonedDateTime all represent the same moment, a date with time-of-day and an assigned time zone.

With a ZonedDateTime in hand, you can generate a String in standard ISO 8601 format extended to append the name of the time zone in square brackets.

String output = zdt.toString() ;  // Generate string in standard ISO 8601 format extended by appending the name of time zone in square brackets.

2018-07-07T15:20:14.372-07:00[America/Los_Angeles]

You can generate strings in other formats using DateTimeFormatter class. For the formatting pattern listed second in your question, define a matching DateTimeFormatter object.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss.SSS" ) ;
String output = zdt.format( f ) ;

07/07/2018 15:20:14.372

The first formatting pattern listed in your Question has a Z on the end, which means UTC and is pronounced “Zulu”. To adjust our ZonedDateTime to UTC, simply extract a Instant object. An Instant is always in UTC by definition.

Instant instant = zdt.toInstant() ;  // Extract an `Instant` object, always in UTC.

Generate a String in the pattern shown first in the Question.

String output = instant.toString() ;  // Generate string in standard ISO 8601 format.

2018-07-07T22:20:14.372Z


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations. Specification is JSR 310 .

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM