-2

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-14T19: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)

dpr
  • 10,591
  • 3
  • 41
  • 71
  • `2021-03-14T19:00-04:00` is not the same instant as `2021-03-15T00:00:00 UTC`. Why would you expect that result? Look at the offsets on the two ZDT's carefully. They're different. – Sweeper Mar 24 '21 at 13:29
  • I agree (Offset is not manually set)-> but how would i get my expected result as daylight saving change on 14th of March – srikanthinu Mar 24 '21 at 13:38
  • I'm not sure your expectation is correct. Have you considered that you might be expecting the wrong thing? If you are sure that you are expecting the correct thing, why deal with New York at all? Just use UTC from the get-go. `LocalDate.of(2021, 3, 15).atStartOfDay(ZoneOffset.UTC).toInstant()`. – Sweeper Mar 24 '21 at 13:44
  • 1
    The actual result is March 13, but the expected result is March 14? Your expected and actual outputs show only one date, but your code is doing both. Please edit your question and decide which one is the problem, or update your expected and actual outputs to reflect your entire code block. – VGR Mar 24 '21 at 14:13
  • 1
    As an aside you can leave out the `withZoneSameInstant` call. It doesn’t make any difference here. – Ole V.V. Mar 24 '21 at 14:20
  • 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) – srikanthinu Mar 24 '21 at 14:53
  • I don't really get your use case. 2021-03-14 is a client holiday. And the users in New York need to work on this day? What would be the holiday in New York that corresponds to 2021-03-14? – dpr Mar 25 '21 at 09:56

2 Answers2

2

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.

dpr
  • 10,591
  • 3
  • 41
  • 71
  • So you are saying that `zonedDateTime2` is not in EST, but in EDT (Eastern Daylight Time). And the UTC offset in the output in the question, `-04:00`, confirms. – Ole V.V. Mar 24 '21 at 14:22
  • 1
    Correct, I updated the answer to make this more clear – dpr Mar 24 '21 at 14:29
0

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
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    Thanks for detailed example. One Caveat is our clients are on multiple time zones (all around the world) . I can't use Eastern Time for all clients, it has to be client specific timezone – srikanthinu Mar 24 '21 at 15:40
  • I suppose that you know the time zone of each client? (Otherwise I believe you’ve got problems.) – Ole V.V. Mar 24 '21 at 15:41
  • Yes i know the client time zone, may be i need to start using US/Eastern or US/Central – srikanthinu Mar 24 '21 at 15:58
  • US/Eastern is just the deprecated name for America/New_York. It won’t buy you anything. – Ole V.V. Mar 24 '21 at 16:18