【问题标题】:Why is the time difference off when subtracting the same date from two different time zones?为什么从两个不同的时区减去相同的日期时时差会消失?
【发布时间】:2021-09-22 19:11:33
【问题描述】:

以下是尝试计算时区之间小时差的示例。

import java.util.*;
import java.text.*;

public class ForPosting
{
   public static void main (String[] args)
   {
       try {
               String myDateString = "07-13-2021 11:00:00";
        
               SimpleDateFormat localDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
               SimpleDateFormat utcDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
               
               localDateTime.setTimeZone(TimeZone.getTimeZone("EET"));
               System.out.println(localDateTime.parse(myDateString));
               
               utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
               System.out.println(utcDateTime.parse(myDateString));
               float diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
               System.out.println("EET & UTC Time Difference : " +  diff);

               localDateTime.setTimeZone(TimeZone.getDefault());
               System.out.println(localDateTime.parse(myDateString));
               
               utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
               System.out.println(utcDateTime.parse(myDateString));
               diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
               System.out.println("Default & UTC Time Difference : " +  diff);
               
               
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
   }
} 

以上代码生成如下输出。

Default & UTC Time Difference : 4.0 通过检查当前日期得到确认,并确认有 4 小时的差异。

对 EET 和 UTC 进行相同的检查是不同的。

EET & UTC Time Difference : -3.0

输出显示有 3 小时的差异,但以下显示只有 2 小时。

为什么 EET 和 UTC 实际时间显示 2 小时时差,而 Java 代码显示 3 小时时差?

【问题讨论】:

  • Google 给您的结果具有误导性。请改用 EEST,它应该会给出该时区的实际时间,截至目前,在 Google 上。
  • 谢谢,现在时间和小时差确实匹配了。
  • UTC 很好,但不要使用其他时区缩写,如EET。改为传递完整的时区标识符,例如 Europe/Sofia使用 EET 的其他时区。见en.wikipedia.org/wiki/List_of_tz_database_time_zones
  • 我建议你不要使用SimpleDateFormatTimeZone。这些类设计不良且过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APIDateTimeFormatterZoneId
  • Lais Bento 很有帮助地问,因为有疑问:可能是因为 EET 是夏季时间? 正如您在我的回答中看到的那样,这是一个非常好的问题,并且没有明确的答案。

标签: java timezone


【解决方案1】:

EET 不是时区

EET 是欧洲和北非大约 20 个时区的通用缩写,在标准时间与 UTC 相差 +02:00。许多(并非所有人)都使用夏令时(夏令时),缩写为东欧夏令时的 EEST,因此在 7 个“夏季”月份中的偏移量为 +03:00。所以当你要求EET 时,你会得到什么,我不知道。所以不要那样做。使用正确的时区 ID,例如 Europe/Uzhgorod,始终采用 region/city 格式。这样你就知道你得到了什么。

所以回答你的问题:

为什么 EET 和 UTC 实际时间显示 2 小时差异而 Java 代码显示相差 3 小时?

因为他们对 EET 的解释不同。这两种解释都是完全有效的,没有一个是权威的。

这对 EET 来说没什么特别的。许多两个、三个、四个和五个字母的时区缩写是常用的。其中很多都是模棱两可的,比如 EET。而且其中很多都不是时区。可能在某些情况下,您可以使用一个与用户进行非正式交流,例如,在用户非常了解上下文中的每一个含义的情况下,仅用于区分 EET 和 EEST。您当然不能依赖它们在您的程序中定义时区。

java.time

我建议您使用现代 Java 日期和时间 API java.time 进行日期和时间工作。查找某个时区与 UTC 之间的差异:

    ZoneId zone = ZoneId.of("Europe/Uzhgorod");
    Instant when = Instant.now();
    
    ZoneOffset differenceFromUtc = when.atZone(zone).getOffset();
    
    System.out.format("%s & UTC Time Difference : %s%n", zone, differenceFromUtc);

刚刚运行时的输出:

欧洲/乌日哥罗德和 UTC 时差:+03:00

现在欧洲/乌日哥罗德是夏天,3 小时的差异来自那个时区使用夏令时。在冬天尝试一下:

    Instant when = Instant.parse("2022-01-01T00:00:00Z");

欧洲/乌日哥罗德和 UTC 时差:+02:00

正如我所说,一些东欧时区不使用夏令时。尝试其中之一:

    ZoneId zone = ZoneId.of("Europe/Kaliningrad");
    Instant when = Instant.now();

欧洲/加里宁格勒和 UTC 时差:+02:00

次要 cmets 到您的代码

虽然 UTC 用于定义时区,但规范 ID 是 Etc/UTC。 Etc 是不属于明确定义的地理区域的时区的伪区域,包括 Etc/UTCEtc/GMT 以及像 Etc/GMT-2 这样的整小时偏移量的 ID(对于偏移量 +02:00 ,符号是倒置的)。

将除法结果分配给float 对您没有帮助。您将long 值除以int 值,结果总是被截断为long 数字。分配给float 时,您仍将始终拥有一个整数。如果您想要分数作为结果,则需要在除法之前将至少一个操作数转换为float(或double)。

还有一个有趣的细节,你的代码测量了 EET 11 点和 UTC 11 点之间的小时差。你得到一个结果正是因为这两个时刻之间有 3 个小时。我不太高兴的是,您没有在明确定义的时间点测量差异。相反,在我的代码中,我选择了一个时间点并在该时间点找到差异。

Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

  • 开始越来越多地了解为什么这三个字母的时区会被贬值。这不是第一次引起这样的冲突。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
相关资源
最近更新 更多