【问题标题】:What is the right way to format Time between different timezones?在不同时区之间格式化时间的正确方法是什么?
【发布时间】:2018-05-30 09:40:53
【问题描述】:

我想将 19:19:00 这样的时间格式化为不同的时区。如果我使用SimpleDateFormat,它总是考虑到纪元的开始:1970.01.01。

一些时区在纪元开始和现在有不同的偏移量。例如,现在与欧洲/基辅的默认偏移量是 UTC+0200,但在 1970 年是 UTC+0300。这意味着如果我在 Europe/Kiev 下运行我的服务器,在 Europe/Berlin(UTC+0100) 下登录的客户端将看到三个小时而不是两个小时。

我可以通过为java.sql.Time 编写自定义格式化程序来解决这个问题。但我想问一下,也许有一些常见的方法或 Java 工具/库可以解决它。

另一种解决方案是使用 joda-time:

TimeZone.setDefault(TimeZone.getTimeZone("Europe/Kiev"));
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Kiev"));

DateTimeFormat.forPattern("HH:mm:ss.SSS")
   .withZone(DateTimeZone.forID("Europe/Berlin"))
   .print(Time.valueOf("19:00:00").getTime());

【问题讨论】:

  • java.time 怎么样,你试过了吗?

标签: java formatting timezone jodatime


【解决方案1】:

您不能只是将时间格式化为不同的时区。你需要一个约会。

如果你想假设那个时间的日期是今天,你可以试试这个代码:

ZoneId originalZone = ZoneId.of("Europe/Kiev");
ZoneId targetZone = ZoneId.of("Europe/Berlin");
LocalTime originalTime = LocalTime.parse("19:19:00");
LocalTime convertedTime = LocalDate.now(originalZone)
                            .atTime(originalTime)
                            .atZone(originalZone)
                            .withZoneSameInstant(targetZone)
                            .toLocalTime();
System.out.println(convertedTime);

【讨论】:

  • 好点,你需要假设一个日期。使用java.time 显然是个好主意。你的代码是不是有点复杂?我会做类似LocalDate.now(originalZone).atTime(LocalTime.parse("19:19:00")).atZone(originalZone).withZoneSameInstant(targetZone).toLocalTime() 的事情。
  • 我可以轻松地将时间格式化为时间戳,因为有日期部分知道该日期的时区。但我想格式化没有日期部分的时间。
  • LocalDate.now(originalZone).atTime(LocalTime.parse("19:19:00")).atZone(originalZone).withZoneSameInstant(targetZone).toLocalTime() 将根据返回不同的结果夏令时日期和规则。
  • @OleV.V.已编辑。
  • @V.Spachynskyi 所以你不想关心夏令时?为什么不呢?
【解决方案2】:

java.time.instant 是您的替代品吗?它在内部将所有时间戳作为 UTC 时间处理。

从字符串中解析它的一种方法是Instant.parse("2018-05-30T19:00:00")

如果您想获得特定时区的时间,您可以通过myInstant.atZone("Zone")获得它

【讨论】:

    【解决方案3】:
        ZoneId originalZone = ZoneId.of("Europe/Kiev");
        ZoneId targetZone = ZoneId.of("Europe/Berlin");
        LocalDate assumedDate = LocalDate.now(originalZone);
        String formattedTime = assumedDate.atTime(LocalTime.parse("19:19:00"))
                .atZone(originalZone)
                .withZoneSameInstant(targetZone)
                .format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        System.out.println(formattedTime);
    

    今天打印出来:

    18:19:00

    当您知道日期时,当然应该使用它而不是今天。在基辅和柏林的情况下,我认为他们遵循相同的夏令时 (DST) 规则,因此准确的日期可能并不重要。如果在不使用相同转换的区域之间转换,或者在使用夏令时的时区和不使用夏令时的时区之间转换,这突然变得至关重要。谁知道明年政客们会在这两个国家中的哪个国家改变规则?最好是安全的。

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

    【讨论】:

      猜你喜欢
      • 2010-12-28
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多