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.
tl;dr
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.
java.time
The modern approach uses the java.time classes that years ago supplanted SimpleDateFormat
, XMLGregorianCalendar
, GregorianCalendar
, and such.
Convert legacy <——> modern
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 to offset of zero
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.
Truncation
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 ) ;
ISO 8601
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() ;