Reputation: 2619
What is the best way to convert XMLGregorianCalendar objects to 'MM/dd/yyyy hh:mm' String?
Upvotes: 29
Views: 75298
Reputation: 131
{
XMLGregorianCalendar xmlCalendar = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(new GregorianCalendar());
OffsetDateTime dt = xmlCalendar.toGregorianCalendar()
.toZonedDateTime().toOffsetDateTime();
return DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm").format(dt);
}
Upvotes: 1
Reputation: 1
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
Upvotes: 0
Reputation: 340118
Use java.time classes, never terribly-flawed legacy classes.
myXMLGregorianCalendar
.toGregorianCalendar() // Convert to another legacy class, `GregorianCalendar`.
.toZonedDateTime() // Convert to modern class, `ZonedDateTime`.
.format( // Generate text.
DateTimeFormatter
.ofPattern( "MM/dd/uuuu HH:mm" ) // Specify custom format. Consider instead automatically localizing rather than hard-code a format.
) // Returns a `String`.
Avoid the terribly-flawed legacy date-time classes. They were supplanted long ago by the modern java.time classes defined in JSR 310, and built into Java 8+.
ZonedDateTime
If handed a XMLGregorianCalendar
object, immediately convert to java.time object. That would be a java.time.ZonedDateTime
object.
We can get to a ZonedDateTime
by way of the legacy class GregorianCalendar
.
ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime();
DateTimeFormatter
Generate text in standard ISO 8601 format wisely extended to include the name of the time zone in square brackets.
String output = zdt.toString() ;
Generate text in localized format.
Locale locale = Locale.of( "fr" , "CA" ) ; // French language, Canada cultural norms.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale );
String output = zdt.format( f ) ;
Or specify a custom format.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm" ) ;
String output = zdt.format( f ) ;
Upvotes: 1
Reputation: 617
Please check this static utility. You just mentioned a pattern like "ddMMyy" or "HHmm" or what ever you want.. this will work wonderfully.
public static String getDateTime(XMLGregorianCalendar gDate, String pattern){
return Optional.ofNullable(gDate)
.map(gdate -> {
Calendar calendar = gDate.toGregorianCalendar();
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
formatter.setTimeZone(calendar.getTimeZone());
return formatter.format(calendar.getTime());
})
.orElse(null);
}
Upvotes: 0
Reputation: 1803
This example convert XMLGregorianCalendar to date
XMLGregorianCalendar xmlCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar());
Date date = xmlCalendar.toGregorianCalendar().getTime();
This example convert date to string
DateFormat df = new SimpleDateFormat("MM/dd/yyyy hh:mm");
String dateStr = df.format(GregorianCalendar.getInstance().getTime());
Upvotes: 0
Reputation: 4907
You can use
toGregorianCalendar()
method for this.
E.g.:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm");
String date = sdf.format(xmlGregorianCalendar.toGregorianCalendar().getTime());
In case, you need to convert that calendar to different TimeZone and Locale, use toGregorianCalendar(TimeZone timezone, Locale aLocale, XMLGregorianCalendar defaults)
Upvotes: 11
Reputation: 1109635
First use XMLGregorianCalendar#toGregorianCalendar()
to get a java.util.Calendar
instance out of it.
Calendar calendar = xmlGregorianCalendar.toGregorianCalendar();
From that step on, it's all obvious with a little help of SimpleDateFormat
the usual way.
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm");
formatter.setTimeZone(calendar.getTimeZone());
String dateString = formatter.format(calendar.getTime());
I only wonder if you don't actually want to use HH
instead of hh
as you aren't formatting the am/pm marker anywhere.
Upvotes: 45
Reputation: 13792
This is an example you are looking for:
XMLGregorianCalendar date = ...; // initialization is out of scope for this example
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm");
GregorianCalendar gc = date.toGregorianCalendar();
String formatted_string = sdf.format(gc.getTime());
Upvotes: 1