简体   繁体   English

ZonedDateTime 到 java.util.Date -> EST 到 UTC - 关闭 1 小时

[英]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我正在尝试将 ZonedDateTime (EST) 转换为 Date (UTC) 我看到 3 月 13 日和 14 日有 1 小时的休息时间

SystemDefault - UTC系统默认值 - 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] EST -> 2021-03-13T19:00-05:00[美国/纽约]
UTC -> Sun Mar 14 00:00:00 UTC 2021 UTC -> 2021 年 3 月 14 日星期日 00:00:00 UTC
EST -> 2021-03-14T19:00-04:00[America/New_York] EST -> 2021-03-14T19:00-04:00[美国/纽约]
UTC -> Sun Mar 14 23:00:00 UTC 2021 UTC -> 2021 年 3 月 14 日星期日 23:00:00 UTC

Expected Result :预期结果
EST -> 2021-03-13T19:00-05:00[America/New_York] EST -> 2021-03-13T19:00-05:00[美国/纽约]
UTC -> Sun Mar 14 00:00:00 UTC 2021 UTC -> 2021 年 3 月 14 日星期日 00:00:00 UTC
EST -> 2021-03-14T 19:00-04:00 [America/New_York] EST -> 2021-03-14T 19:00-04:00 [美国/纽约]
UTC -> Mon Mar 15 00:00:00 UTC 2021 UTC -> 2021 年 3 月 15 日星期一 00:00:00 UTC

Here is business use case这是业务用例

-> Client specific holidays 2021/1/14, 2021/2/14, 2021/3/14 (These are in UTC) -> 客户特定假期 2021/1/14、2021/2/14、2021/3/14(以 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) -> 用户选择一个具体的时间 eg: 2021/2/14 19:00, 2021/3/14 19:00 EST (这两天是实际工作日)

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)为此,我将用户选择的日期(EST)转换为 UTC 并检查客户特定的日历(它适用于 2 月,但 3 月失败)

On Sun March 14th daylight saving time started in America/New_York . 3 月 14 日星期日,夏令时在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 . America/New_York的夏令时开始于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.也就是说,在此之后的任何日期时间实例(直到冬季时间再次生效)对于时区America/New_York将是 EDT 而不是 EST。 And EDT has a UTC offset of -4 hours. EDT 的 UTC 偏移量为 -4 小时。

Using EST all year全年使用 EST

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.有些时区可以做到这一点,因此解决方案是:不要使用 America/New_York 时区,而是使用使用东部时间且不使用夏令时/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): Output 是(在 UTC 时区运行时):

 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.时区 ID 现在是 America/Atikokan。
  2. The UTC offset for 2021-03-14T19:00 is now not -04:00 but -05:00 . 2021-03-14T19:00的 UTC 偏移现在不是-04:00而是-05:00 Which is what causes the time to be converted to the expected UTC time of 00:00.这就是导致时间转换为预期 UTC 时间 00:00 的原因。

Compared to your code I have made one other change: I have left the calls to withZoneSameInstant() out.与您的代码相比,我进行了另一项更改:我已将调用withZoneSameInstant()排除在外。 They make no difference here.他们在这里没有任何区别。 Since you are doing toInstant() afterward, as the method names say, you get the same instant in both cases.由于您之后执行toInstant() ,正如方法名称所说,您在两种情况下都会获得相同的瞬间。

Edit: North and Central American time zones using Eastern Standard Time all year include:编辑:全年使用东部标准时间的北美和中美洲时区包括:

  • In Canada: America/Atikokan在加拿大:美国/Atikokan
  • In the US: None that I have found在美国:我没有找到
  • In Central America and the Caribbeans: America/Cancun, America/Jamaica, America/Panama在中美洲和加勒比地区:美洲/坎昆、美洲/牙买加、美洲/巴拿马

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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