【问题标题】:How to change timezone without changing the time?如何在不更改时间的情况下更改时区?
【发布时间】:2018-07-24 09:16:38
【问题描述】:

我有一个 UTC 时间戳 2018-01-01 18:20:23.11。我需要以不同的格式打印它,但保留 UTC 时区。但是,如果我使用 SimpleDateFormat(“dd MMM YYYY yyyy kk:mm z”),它会占用我当前的时区并给我 2018 年 1 月 1 日 18:20 EST。我希望它打印 2018 年 1 月 1 日 18:20 UTC。执行 Timezone.getTimeZone("UTC") 会将此时间转换为 UTC(将 +4 转换为小时),这不是所需的结果。

【问题讨论】:

标签: java date datetime simpledateformat


【解决方案1】:
    DateTimeFormatter originalFormatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SS");
    DateTimeFormatter newFormatter
            = DateTimeFormatter.ofPattern("dd MMM uuuu HH:mm z", Locale.ENGLISH);
    String originalTimestamp = "2018-01-01 18:20:23.11";
    String differentFormat = LocalDateTime.parse(originalTimestamp, originalFormatter)
            .atZone(ZoneId.of("Etc/UTC"))
            .format(newFormatter);
    System.out.println(differentFormat);

打印出来

01 Jan 2018 18:20 UTC

ZoneId.of("Etc/UTC")ZoneOffset.UTC?

一个可能是书呆子的编辑:我首先在转换中写了.atZone(ZoneOffset.UTC)。我通常使用ZoneOffset.UTC 来表示 UTC,并认为这是一种很好的惯用方式来指定它。但是,对于您的代码,这会导致在您要求UTC 的输出中将区域指定为Z。使用 ZoneId.of("Etc/UTC") 可以给你想要的东西。我找不到其他方法来确保该区域被格式化为UTC(在格式模式字符串中保存硬编码UTC,但这将是一个丑陋的hack)。

顺便说一句,ZoneId.of("Etc/UTC").normalized() 返回 ZoneOffset.UTC(至少在我的 Java 10 上,但我希望它总是如此)。

SimpleDateFormat 与 java.time

SimpleDateFormat 不仅已经过时,而且出了名的麻烦。我建议你避免它。正如您所观察到的,它使用 JVM 的默认时区是正确的。有办法说服它采取不同的做法,但我不会打扰。

java.time 是现代 Java 日期和时间 API。它于 2014 年问世,作为旧的和设计不佳的日期和时间类的替代品。恕我直言,与它一起工作要好得多。

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

【讨论】:

  • 为什么不用ZoneOffset.UTC 而不是ZoneId.of("Etc/UTC")
  • 有趣的是 ZoneOffset.UTCZoneId.of("Etc/UTC") 表现出不同的行为。谢谢。我建议将其添加为您的答案中感兴趣的注释。
  • 哇,太棒了,很棒的 java 来改变时区,我们需要这么多代码,不是很遗憾吗?
猜你喜欢
  • 2023-03-17
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2021-01-31
  • 2019-11-01
  • 2014-12-23
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多