Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Fix incorrect timezone in date object

An external API returns an object with a date.
According to their API specification, all dates are always reported in GMT.

However, the generated client classes (which I can't edit) doesn't set the timezone correctly. Instead, it uses the local timezone without converting the date to that timezone.

So, long story short, I have an object with a date that I know to be GMT but it says CET. How can I adjust for this mistake withouth changing my local timezone on the computer or doing something like this:

LocalDateTime.ofInstant(someObject.getDate().toInstant().plus(1, ChronoUnit.HOURS),
                        ZoneId.of("CET"));

Thank you.

like image 249
Christoph Strehl Avatar asked May 22 '26 11:05

Christoph Strehl


1 Answers

tl;dr ⇒ use ZonedDateTime for conversion

public static void main(String[] args) {
    // use your date here, this is just "now"
    Date date = new Date();
    // parse it to an object that is aware of the (currently wrong) time zone
    ZonedDateTime wrongZoneZdt = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("CET"));
    // print it to see the result
    System.out.println(wrongZoneZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));

    // extract the information that should stay (only date and time, NOT zone or offset)
    LocalDateTime ldt = wrongZoneZdt.toLocalDateTime();
    // print it, too
    System.out.println(ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

    // then take the object without zone information and simply add a zone
    ZonedDateTime correctZoneZdt = ldt.atZone(ZoneId.of("GMT"));
    // print the result
    System.out.println(correctZoneZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

Output:

2020-01-24T09:21:37.167+01:00[CET]
2020-01-24T09:21:37.167
2020-01-24T09:21:37.167Z[GMT]

Explanation:

The reason why your approach did not just correct the zone but also adjusted the time accordingly (which is good when desired) is your use of a LocalDateTime created from an Instant. An Instant represents a moment in time which could have different representations in different zones but it stays the same moment. If you create a LocalDateTime from it and put another zone, the date and time are getting converted to the target zone's. This is not just replacing the zone while keeping the date and time as they are.

If you use a LocalDateTime from a ZonedDateTime, you extract the date and time representation ignoring the zone, which enables you to add a different zone afterwards and keep the date and time as it was.

Edit: If the code is running in the same JVM as the faulty code, you can use ZoneId.systemDefault() to get the same time zone as the faulty code is using. And depending on taste you may use ZoneOffset.UTC instead of ZoneId.of("GMT").

like image 177
deHaar Avatar answered May 24 '26 00:05

deHaar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!