Reputation: 8955
I have a String date I am converting to a XMLGregorianCalendar
. The below code converts it with no errors. However, the system I pass the date to, gets the error reported below.
The following XMLGregorianCalendar
works:
The following XMLGregorianCalendar
does not work (the code below converts it to this):
Question
How do I convert the string to the required format?
public static void main(String []args){
try {
String commenceTOString = "2021-06-30 05:00:00";
java.util.Date dateCommence = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(commenceTOString);
System.out.println(dateCommence);
java.util.GregorianCalendar c = new java.util.GregorianCalendar();
c.setTime(dateCommence);
javax.xml.datatype.XMLGregorianCalendar commence = javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
System.out.println(commence);
} catch (Exception e) {
e.printStackTrace();
}
}
Error
E: Message validation failed. Errors: [cvc-pattern-valid: Value '2021-06-30T06:30:00.000+02:00' is not facet-valid with respect to pattern '(((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-9])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-30)))|(((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))T([0-1][0-9]|[2][0-3])(:([0-5][0-9])){1,2}' for type 'dateTime'.cvc-attribute.3: The value '2021-06-30T06:30:00.000+02:00' of attribute 'DepartureDateTime' on element 'FlightSegment' is not valid with respect to its type, 'dateTime'.]. http://www.elleipsis.com/booking/exception/35a8ac87-6743-4719-9504-a8a17a1a0471
Upvotes: 2
Views: 6255
Reputation: 86369
There are many ways to do this. Generally I recommend that you use java.time for your date and time work, also when there is no direct conversion between java.time classes and XMLGregorianCalendar
.
The hack is simply to edit the T
into the string that XMLGregorianCalendar
expects to be there and then parse the modified string directly. Then we neither need java.time nor Date
nor SimpleDateFormat
.
String commenceTOString = "2021-06-30 05:00:00";
XMLGregorianCalendar commence = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(commenceTOString.replace(' ', 'T'));
System.out.println(commence);
Output:
2021-06-30T05:00:00
Parse into LocalDateTime
, format into a string in the format XMLGregorianCalendar
knows and let the DatatypeFactory
parse again:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(commenceTOString, parser);
XMLGregorianCalendar commence = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(dateTime.format(formatter));
System.out.println(commence);
Output is the same as before.
Though a few lines longer this is the conceptually simple conversion: transfer each field from LocalDateTime
to XMLGregorianCalendar
.
XMLGregorianCalendar commence = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(
dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(),
dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(),
DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);
System.out.println(commence);
Output is still the same.
I believe that this is the official conversion: convert to ZonedDateTime
to GregorianCalendar
and finally to XMLGregorianCalendar
. We need to set the unwanted field to FIELD_UNDEFINED
just as in your own answer.
ZonedDateTime dateTime = LocalDateTime.parse(commenceTOString, parser)
.atZone(ZoneOffset.UTC);
GregorianCalendar gc = GregorianCalendar.from(dateTime);
XMLGregorianCalendar commence = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gc);
commence.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
commence.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
System.out.println(commence);
Oracle tutorial: Date Time explaining how to use java.time.
Upvotes: 1
Reputation: 8955
This fixed it for me: (using DatatypeConstants.FIELD_UNDEFINED
)
GregorianCalendar c = new GregorianCalendar();
c.setTime(dateCommence);
XMLGregorianCalendar commence = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
commence.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
commence.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
Upvotes: 0