kostepanych
kostepanych

Reputation: 2619

What is the best way to convert XMLGregorianCalendar to MM/dd/yyyy hh:mm String?

What is the best way to convert XMLGregorianCalendar objects to 'MM/dd/yyyy hh:mm' String?

Upvotes: 29

Views: 75298

Answers (8)

yv84_
yv84_

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

Noah Smith
Noah Smith

Reputation: 1

What does your XMLGregorianCalendar look like?

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.

java.time

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

Basil Bourque
Basil Bourque

Reputation: 340118

tl;dr

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`. 

java.time

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

atul sachan
atul sachan

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

David Pham
David Pham

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

Ostap Andrusiv
Ostap Andrusiv

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

BalusC
BalusC

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

Miguel Prz
Miguel Prz

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

Related Questions