Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert XMLGregorianCalendar to java.time.Instant + switch timezone in the meanwhile

Tags:

java

timezone

I'm trying to convert a variable given in XMLGregorianCalendar to java.time.Instant. Besides, the original variable is in Central Standard Time (America/Chicago) and I would need it in UTC. That's what I did, but it returns an Instant in UTC-7:

XMLGregorianCalendar xgc = header.getCaptureDate();
Instant convertedDateTime = xgc.toGregorianCalendar().toInstant().atOffset(ZoneOffset.UTC).toInstant();

I'm really confused what I'm doing wrong.

The xgc looks like this: 2018-04-13T06:30:23, and I would need this: 2018-04-13T11:30:23Z (Z added to the end, plus timezone changed). However, now I get this: 2018-04-13T04:30:23Z.

like image 355
Antona Avatar asked Sep 14 '25 14:09

Antona


1 Answers

Thanks for the cooperation in finding a solution. I agree to your last comment:

    Instant convertedDateTime = xgc.toGregorianCalendar()
            .toZonedDateTime()
            .withZoneSameLocal(ZoneId.of("America/Chicago"))
            .toInstant();
    System.out.println(convertedDateTime);

It prints the desired

2018-04-13T11:30:23Z

An Instant doesn’t have a time zone. It’s toString method (called implicitly when we print it) produces a string in UTC. The Z at the end of the string means UTC or offset zero.

Since we are giving a real time zone (America/Chicago), the code will adjust for summer time (daylight saving time) for us. The only issue here is when in the fall the clock is turned backward. For example, November 4, 2018, the clock will be turned backward from 2 to 1, so if we get a time between 1 and 2, we cannot know whether it is in DST or not. Had your XMLGregorianCalendar had a UTC offset in it, it would have given us an unambiguous point in time. But we had to supply that ourselves, which is what the withZoneSameLocal call did.

What went wrong in your code?

I suppose that your JVM’s time zone setting is some Central European time zone (such as Europe/Oslo or Europe/Rome) which is on DST on April 13, that is, at UTC offset +02:00 (AKA CEST). The XMLGregorianCalendar not having an offset in it, the conversion to Instant assumed that the time was in this time zone, so converted to 2018-04-13T04:30:23Z. Converting to OffsetDateTime and back to Instant made no difference. You noted that it was 7 hours too early and assumed it was in time zone offset UTC-7 (which it wasn’t; Z still means UTC).

like image 147
Ole V.V. Avatar answered Sep 17 '25 03:09

Ole V.V.