Search code examples
javatimezoneutcjava-timedatetime-conversion

How to convert ZULU timestamp to Europe/Paris time zone?


I have a ZULU timestamp that I have to convert into Paris time zone.

ZULU 2022-11-04T06:10:08.606+00:00  --> Paris 2022-11-04T07:10:08.606+01:00

And have to take care of DST for example: Summer time Hour +2 hour Winter time Hour +1 hour

I have written the below code which is working as expected on the local but when deploy on the server (Paris) not working as expected.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Locale;

public class ParisTime {

    public static void main(String[] args) throws ParseException {

        // String date = "2022-05-31T23:30:12.209+00:00";
        String date = "2022-11-04T06:10:08.606+00:00";

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
        LocalDateTime dateTime = dateFormat.parse(date).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        ZonedDateTime of = ZonedDateTime.of(dateTime, ZoneId.of("Europe/Paris"));
        String hourDiff = of.toString().substring(of.toString().indexOf('+') + 1, of.toString().indexOf('+') + 3);
        String zonedDateTime = of.plusHours(Integer.valueOf(hourDiff)).toString();
        String newDatetime = zonedDateTime.substring(0, of.toString().indexOf('['));

        System.out.println(newDatetime);

        System.out.println(dateFormat.parse(newDatetime));
    }
}

Output

2022-11-04T07:10:08.606+01:00
Fri Nov 04 07:10:08 IST 2022

Solution

  • You can directly switch between zones and offsets using plain java.time, no legacy baggage necessary…

    Here's how:

    • your input example is an ISO-formatted datetime with an offset from UTC (of 0 hours and 0 minutes, so it is Zulu time respectively in UTC), which means you can parse it in one go to a java.time.OffsetDateTime
    • an OffsetDateTime can be converted into a ZonedDateTime
    • a ZonedDateTime can handle daylight saving time (DST)
    • having a ZonedDateTime you can switch its ZoneId, which will respect DST, but keep the underlying instant

    Please see the following example…

    public static void main(String[] args) {
        // input example
        String date = "2022-11-04T06:10:08.606+00:00";
        // directly parse it to a java.time.OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse(date);
        // make the UTC/Zulu datetime zoned
        ZonedDateTime zdt = odt.toZonedDateTime();
        // print it
        System.out.println(zdt);
        // switch the zone to the desired one
        ZonedDateTime zdtParis = zdt.withZoneSameInstant(ZoneId.of("Europe/Paris"));
        // print that, too
        System.out.println(zdtParis);
        // or print a coversion to OffsetDateTime without explicitly mentioning the zone
        System.out.println(zdtParis.toOffsetDateTime());
        // the same can be achieved keeping the ZonedDateTime but formatting it as OffsetDateTime
        System.out.println(zdtParis.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
    }
    

    The output of the above code is

    2022-11-04T06:10:08.606Z
    2022-11-04T07:10:08.606+01:00[Europe/Paris]
    2022-11-04T07:10:08.606+01:00
    2022-11-04T07:10:08.606+01:00
    

    Try it with a datetime influenced by DST, you will see DST respected… This is the output of the same code using the input value "2022-05-31T23:30:12.209+00:00":

    2022-05-31T23:30:12.209Z
    2022-06-01T01:30:12.209+02:00[Europe/Paris]
    2022-06-01T01:30:12.209+02:00
    2022-06-01T01:30:12.209+02:00