简体   繁体   中英

ZonedDateTime to java.util.Date -> EST to UTC - Off by 1 hour

I'm trying to convert ZonedDateTime (EST) to Date (UTC) i see 1 hour off for the month of march for 13 and 14th calendar date

SystemDefault - UTC

ZonedDateTime zonedDateTime1 = ZonedDateTime.of(2021, 3, 13, 19, 0, 0, 0, ZoneId.of("America/New_York")); 

Date date1 = Date.from(zonedDateTime1.withZoneSameInstant(ZoneId.systemDefault()).toInstant();

System.out.println("EST -> ", zonedDateTime1);
System.out.println("UTC -> ", date1);

ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2021, 3, 14, 19, 0, 0, 0, ZoneId.of("America/New_York")); 

Date date2 = Date.from(zonedDateTime2.withZoneSameInstant(ZoneId.systemDefault()).toInstant();
 
System.out.println("EST -> ", zonedDateTime2);
System.out.println("UTC -> ", date2);

Actual Result :
EST -> 2021-03-13T19:00-05:00[America/New_York]
UTC -> Sun Mar 14 00:00:00 UTC 2021
EST -> 2021-03-14T19:00-04:00[America/New_York]
UTC -> Sun Mar 14 23:00:00 UTC 2021

Expected Result :
EST -> 2021-03-13T19:00-05:00[America/New_York]
UTC -> Sun Mar 14 00:00:00 UTC 2021
EST -> 2021-03-14T 19:00-04:00 [America/New_York]
UTC -> Mon Mar 15 00:00:00 UTC 2021

Here is business use case

-> Client specific holidays 2021/1/14, 2021/2/14, 2021/3/14 (These are in UTC)

-> user selects a specific time eg: 2021/2/14 19:00, 2021/3/14 19:00 EST (These two days are actual working days)

Now system has say user selected date is a holiday or working day for client

For this I converted user selected date (EST) to UTC and checking against client specific calendar (it works for feb but fails for march)

On Sun March 14th daylight saving time started in America/New_York . I suppose this is the reason for the observed difference.

Daylight saving time for America/New_York started on 2021-03-14T02:00:00 EST . That is any date time instance after this (until winter time is effective again) for time zone America/New_York will be EDT and not EST. And EDT has a UTC offset of -4 hours.

Using EST all year

It seems that your client insists on reporting times in EST, Eastern Standard Time, all year, not EDT, Eastern Daylight Time, in summer. There are time zones that do that, so a solution is: instead of using America/New_York time zone, use a time zone that uses Eastern Time and doesn't use summer time/DST. For example:

    ZoneId clientTimeZone = ZoneId.of("America/Atikokan");
       
    ZonedDateTime zonedDateTime1 = ZonedDateTime.of(2021, 3, 13, 19, 0, 0, 0, clientTimeZone); 

    Date date1 = Date.from(zonedDateTime1.toInstant());

    System.out.println("EST -> " + zonedDateTime1);
    System.out.println("UTC -> " + date1);

    ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2021, 3, 14, 19, 0, 0, 0, clientTimeZone); 

    Date date2 = Date.from(zonedDateTime2.toInstant());
     
    System.out.println("EST -> " + zonedDateTime2);
    System.out.println("UTC -> " + date2);

Output is (when running in UTC time zone):

 EST -> 2021-03-13T19:00-05:00[America/Atikokan] UTC -> Sun Mar 14 00:00:00 UTC 2021 EST -> 2021-03-14T19:00-05:00[America/Atikokan] UTC -> Mon Mar 15 00:00:00 UTC 2021

Compared to what you expected, the differences are:

  1. The time zone ID is now America/Atikokan.
  2. The UTC offset for 2021-03-14T19:00 is now not -04:00 but -05:00 . Which is what causes the time to be converted to the expected UTC time of 00:00.

Compared to your code I have made one other change: I have left the calls to withZoneSameInstant() out. They make no difference here. Since you are doing toInstant() afterward, as the method names say, you get the same instant in both cases.

Edit: North and Central American time zones using Eastern Standard Time all year include:

  • In Canada: America/Atikokan
  • In the US: None that I have found
  • In Central America and the Caribbeans: America/Cancun, America/Jamaica, America/Panama

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM