1

In Java 8 I need a way to get the local datetime (GMT+1) from a GMT datetime in ISO 8601 format.

A simple example: Client sends me (Server) this datetime "2020-01-11T23:00:00.000Z" Client sends me this when the user choose the 12 Jan 2020 from the datepicker. Is the 12 Jan for GMT+1 but the day before for GMT.

For the reason above then I know that for me this datetime is not the 11 Jan 2020 but 12 Jan 2020 in GMT+1.

So I need this value "2020-01-12T00:00:00.000"

To be precise I don't need to print this with simpleDateFormat but just covert "2020-01-11T23:00:00.000Z" to "2020-01-12T00:00:00.000" in a java.util.Date class field

Thanks.

3
  • I recommend you don’t use SimpleDateFormat and java.util.Date. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. If you are only interested in the date (not the time of day), then use LocalDate from java.time, the modern Java date and time API.
    – Anonymous
    Commented Jan 28, 2021 at 16:46
  • As you say yourself 2020-01-11T23:00:00.000Z and 2020-01-12T00:00:00.000+01:00 are the same point in time. A Date is just a point in time, so two Date objects representing those two times will be identical. There is no conversion to do between them.
    – Anonymous
    Commented Jan 28, 2021 at 16:48
  • Do you know the client time zone or UTC offset? Otherwise you will be at a loss, at least for some input values.
    – Anonymous
    Commented Jan 28, 2021 at 16:49

1 Answer 1

3

The problem is that the source system took the pure date value, but added time at midnight, then converted that to UTC, but you want the pure date value in a java.util.Date, which by default prints in your local time zone, i.e. the JVM's default time zone.

So, you have to parse the string, revert the value back to the time zone of the source system, the treat that local time as a time in your own JVM's default time zone.

You can do that like this, showing all the intermediate types:

String sourceStr = "2020-01-11T23:00:00.000Z";
ZoneId sourceTimeZone = ZoneOffset.ofHours(1); // Use real zone of source, e.g. ZoneId.of("Europe/Paris");

// Parse Zulu date string as zoned date/time in source time zone
Instant sourceInstant = Instant.parse(sourceStr);
ZonedDateTime sourceZoned = sourceInstant.atZone(sourceTimeZone);

// Convert to util.Date in local time zone
ZonedDateTime localZoned = sourceZoned.withZoneSameLocal(ZoneId.systemDefault());
Instant localInstant = localZoned.toInstant();
Date localDate = Date.from(localInstant); // <== This is your desired result

// Print value in ISO 8601 format
String localStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(localDate);
System.out.println(localStr);

Output

2020-01-12T00:00:00.000

The code can of course be merged together:

String input = "2020-01-11T23:00:00.000Z";

Date date = Date.from(Instant.parse(input).atZone(ZoneOffset.ofHours(1))
        .withZoneSameLocal(ZoneId.systemDefault()).toInstant());

System.out.println(date);

Output

Sun Jan 12 00:00:00 EST 2020

As you can see, the date value is correct, even though I'm in the US Eastern time zone.

4
  • I'm not sure I understand what withZoneSameLocal is for. I think Instant.parse("2020-01-11T23:00:00.000Z").atZone(ZoneId.of("GMT+1")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) could already do the trick. Why do we need two ZonedDateTimes; is it just for the OP for easier understanding?
    – 1453
    Commented Jan 28, 2021 at 10:36
  • 1
    @akuzminykh java.util.Date stores values in UTC, but parses and prints values in the default time zone of the JVM, aka the "local" time zone, which is the original of the probem in the first place. On the source server (GMT+1), the "local" date 2020-01-12 aka 2020-01-12T00:00+01:00, is stored in a Date as 2020-01-11T23:00Z. On my machine (US Eastern), the "local" date 2020-01-12 aka 2020-01-12T00:00-05:00 is stored as 2020-01-12T05:00Z. We use withZoneSameLocal to convert from 2020-01-12T00:00+01:00 to 2020-01-12T00:00-05:00.
    – Andreas
    Commented Jan 28, 2021 at 11:01
  • @Andreas thanks for your answer. How the DST is handled in this kind of situation. Is it an issue to deal with or not?
    – HK15
    Commented Jan 28, 2021 at 13:26
  • 1
    @Yuri It is, which is why you should use the real time zone of the source system (e.g. Europe/Paris), instead of a hard-coded GMT+1, as commented in the code.
    – Andreas
    Commented Jan 28, 2021 at 15:27

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.