Reputation: 439
I have a date as input = 2021-03-12T10:42:01.000Z.... and I want to transform into this format:
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
public String getDate(XMLGregorianCalendar input) {
DateFormat f = new SimpleDateFormat(pattern);
input.toGregorianCalendar().setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
String output = f.format(input.toGregorianCalendar().getTime());
System.out.println(output);
}
2021-03-12T12:42:01+0200
Basically, it's adding 2hs more. Maybe it's related with the time zone, I didn't test it in another computer. I have 2 questions:
Thanks
Upvotes: 2
Views: 1101
Reputation: 338181
The Answer by Jon Skeet is correct, and smart. You appear to be seeing simply a time zone adjustment. Your two strings 2021-03-12T10:42:01.000Z
& 2021-03-12T12:42:01+0200
represent the very same moment. The 12 noon hour, if two hours ahead of UTC, is the same as 10 AM hour with an offset-from-UTC of zero hours-minutes-seconds.
And, as mentioned in that other Answer, you really should avoid using the terrible date-time classes bundled with the earliest versions of Java.
myXMLGregorianCalendar // Legacy class, representing a moment as seen in some time zone.
.toGregorianCalendar() // Another legacy class, also representing a moment as seen in some time zone.
.toZonedDateTime() // A modern *java.time* class, representing a moment as seen in some time zone.
.toInstant() // Another *java.time* class, for representing a moment as seen in UTC.
.truncatedTo( // Lopping off some smaller part of the date-time value.
ChronoUnit.SECONDS // Specifying whole seconds as our granularity of truncation, so lopping off any fractional second.
) // Returns another `Instant` object, rather than altering (mutating) the original, per immutable objects pattern.
.toString() // Generating text representing the content of our `Instant` object, using standard ISO 8601 format.
The modern approach uses the java.time classes that years ago supplanted SimpleDateFormat
, XMLGregorianCalendar
, GregorianCalendar
, and such.
You can easily convert from the legacy types to java.time. Look for new to
/from
methods on the old classes.
ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;
Adjust from whatever time zone to UTC by extracting an Instant
. This class represents a moment as seen in UTC, always in UTC.
Instant instant = zdt.toInstant() ;
Understand that zdt
and instant
both represent the same moment, the same point on the timeline, but differ in their wall-clock time.
Given the formatting pattern seen in your Question, you seem want to work with a granularity of whole seconds. To lop off any fractional second, truncate to seconds.
Instant truncated = instant.truncatedTo( ChronoUnit.SECONDS ) ;
Your desired text format is defined in the ISO 8601 standard. That standard is used by default in java.time for parsing/generating strings. So no need to specify any formatting pattern.
String output = truncated.toString() ;
Upvotes: 3
Reputation: 1499790
Basically, it's adding 2hs more
Not really. It's giving you the output for the same instant in time, but in your system local time zone - because you're creating a SimpleDateFormat
without specifying a time zone (or a culture):
DateFormat f = new SimpleDateFormat(pattern);
Personally I'd recommend avoiding using java.text.SimpleDateFormat
entirely, preferring the java.time
types and formatters. But if you definitely want to use SimpleDateFormat
, just make sure you set the time zone to UTC (assuming you always want UTC) and ideally set the culture as well (e.g. to Locale.ROOT
).
Upvotes: 3