XMLGregorianCalendar
is a flexible beast in that each of its fields -- year, month, day, hour, minute, second and UTC offset -- may be defined or undefined (UTC offset is confusingly called timezone in XML parlance). To work with it we first need to know which fields are defined. You probably know that in your case, only you haven‘t told us. For a string containing date and time of day we need those. More precisely I should say that we need year, month, day, hour, minute and second. So I will assume that we have all of those. For UTC offset we either need it to be in the XMLGregorianCalendar
(preferred), or we need to know which time zone was assumed when the XMLGregorianCalendar
was constructed. Under all circumstances we need to know for which time zone to write the string.
I recommend that you use java.time, the modern Java date and time API, to the greatest extend possible for your date and time work. So my code includes converting XMLGregorianCalendar
to a modern type, either OffsetDateTime
or LocalDateTime
depending UTC offset being defined in the XMLGregorianCalendar
.
So a suggestion is:
ZoneId defaultAssumedSourceZone = ZoneId.of("Europe/Tallinn");
ZoneId desiredTargetZone = ZoneId.of("Asia/Kabul");
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar("2013-02-04T13:12:45+01:00");
if (xgcal.getXMLSchemaType() != DatatypeConstants.DATETIME) {
throw new IllegalStateException("We need year, month, day, hour, minute and second; got " + xgcal);
}
ZonedDateTime targetZdt;
if (xgcal.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) { // No UTC offset
LocalDateTime dateTime = LocalDateTime.parse(xgcal.toString());
ZonedDateTime sourceZdt = dateTime.atZone(defaultAssumedSourceZone);
targetZdt = sourceZdt.withZoneSameInstant(desiredTargetZone);
} else { // UTC offset included; use it
OffsetDateTime sourceDateTime = OffsetDateTime.parse(xgcal.toString());
targetZdt = sourceDateTime.atZoneSameInstant(desiredTargetZone);
}
String formattedDateTime = targetZdt.format(formatter);
System.out.println(formattedDateTime);
When running this snippet in US English locale, output was:
2/4/13, 4:42 PM
It‘s not the format you asked for. Please consider it anyway. It‘s Java‘s built-in localized format for the locale, so it‘s likely to make the users in that locale happy. And it adjusts easily to other locales. Run in Spanish locale, for example:
4/2/13, 16:42
If your users insist on MM/dd/yyyy hh:mm
for a reason that I cannot guess, specify that:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm", Locale.ROOT);
02/04/2013 15:42
Let‘s try the code with a XMLGregorianCalendar
with undefined UTC offset too:
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar("2013-02-04T13:12:45");
2/4/13, 3:42 PM