3

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.

9
  • Can you provide example values like parseable Strings? How does the received datetime look? Is it a String or is it an instance of Date or LocalDateTime or even ZonedDateTime? Commented Jan 24, 2020 at 7:44
  • 1
    It is already a java.util.date-object (I'm not parsing anything, the provided and generated client-classes do that, falsely, as described). Commented Jan 24, 2020 at 7:55
  • So for instance my date object.toString() would return Fri Jan 24 09:15:00 CET 2020 when it actually should be Fri Jan 24 09:15:00 GMT 2020 or Fri Jan 24 10:15:00 CET 2020 Commented Jan 24, 2020 at 7:55
  • 3
    @ChristophStrehl a java.util.Date doesn't have a timezone. It prints in the JVM's default timezone. So, if you're in CET, it will print in CET. "According to their API specification, all dates are always reported in GMT" is simply not possible if they return a java.util.Date. Commented Jan 24, 2020 at 8:21
  • @AndyTurner I think that is half the truth. The now deprecated getTimeZoneOffset() method implies that originally the java.util.Date class was designed to also technically contain information about the timezone. Commented Jan 24, 2020 at 8:59

2 Answers 2

2

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").

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, that solution works for me and I also used the adaptions in the comment.
@OleV.V. Thanks for the edit, I would have included it to the answer myself but didn't have time...
0

I am afraid you will not get around some calculations here. I'd strongly suggest to follow an approach based on java.time classes, but alternatively you might use the java.util.Calendar class and myCalendar.get(Calendar.ZONE_OFFSET) for those calculations:

https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#ZONE_OFFSET

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.