【问题标题】:Java: Fix incorrect timezone in date objectJava:修复日期对象中不正确的时区
【发布时间】:2020-01-24 07:28:22
【问题描述】:

外部 API 返回一个带有日期的对象。
根据他们的 API 规范,所有日期始终以 GMT 报告。

但是,生成的客户端类(我无法编辑)没有正确设置时区。相反,它使用本地时区而不将日期转换为该时区。

所以,长话短说,我有一个我知道是 GMT 日期的对象,但它显示的是 CET。如何在不更改计算机上的本地时区或执行以下操作的情况下调整此错误:

LocalDateTime.ofInstant(someObject.getDate().toInstant().plus(1, ChronoUnit.HOURS),
                        ZoneId.of("CET"));

谢谢。

【问题讨论】:

  • 您能提供像可解析Strings 这样的示例值吗?收到的日期时间看起来如何?它是String 还是DateLocalDateTime 甚至ZonedDateTime 的实例?
  • 它已经是一个 java.util.date-object(我没有解析任何东西,提供和生成的客户端类会错误地这样做,如所述)。
  • 因此,例如,我的 date object.toString() 将返回 Fri Jan 24 09:15:00 CET 2020,而实际上应该是 Fri Jan 24 09:15:00 GMT 2020 或 Fri Jan 24 10 :15:00 CET 2020
  • @ChristophStrehl a java.util.Date 没有时区。它以 JVM 的默认时区打印。因此,如果您在 CET 中,它将在 CET 中打印。如果他们返回java.util.Date,“根据他们的 API 规范,所有日期总是以 GMT 报告”是不可能的。
  • @AndyTurner 我认为这是事实的一半。现在已弃用的 getTimeZoneOffset() 方法意味着最初 java.util.Date 类被设计为在技术上也包含有关时区的信息。

标签: java date timezone


【解决方案1】:

tl;dr ⇒ 使用ZonedDateTime 进行转换

public static void main(String[] args) {
    // use your date here, this is just "now"
    Date date = new Date();
    // parse it to an object that is aware of the (currently wrong) time zone
    ZonedDateTime wrongZoneZdt = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("CET"));
    // print it to see the result
    System.out.println(wrongZoneZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));

    // extract the information that should stay (only date and time, NOT zone or offset)
    LocalDateTime ldt = wrongZoneZdt.toLocalDateTime();
    // print it, too
    System.out.println(ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

    // then take the object without zone information and simply add a zone
    ZonedDateTime correctZoneZdt = ldt.atZone(ZoneId.of("GMT"));
    // print the result
    System.out.println(correctZoneZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

输出:

2020-01-24T09:21:37.167+01:00[CET]
2020-01-24T09:21:37.167
2020-01-24T09:21:37.167Z[GMT]

说明:

您的方法不仅纠正了区域而且还相应地调整了时间(这在需要时很好)的原因是您使用了从Instant 创建的LocalDateTimeInstant 代表一个时刻,它在不同的区域可能有不同的表示,但它保持相同的时刻。如果您从中创建LocalDateTime 并放置另一个区域,则日期和时间将转换为目标区域的日期和时间。这不仅仅是在保持日期和时间不变的同时替换区域。

如果您使用ZonedDateTime 中的LocalDateTime,您会提取忽略区域的日期和时间表示,这使您可以在之后添加不同的区域并保持日期和时间不变。

编辑:如果代码与故障代码在同一个 JVM 中运行,您可以使用ZoneId.systemDefault() 获取与故障代码使用的时区相同的时区。根据口味,您可以使用ZoneOffset.UTC 而不是ZoneId.of("GMT")

【讨论】:

  • 谢谢,这个解决方案对我有用,我也使用了评论中的改编。
  • @OleV.V.感谢您的编辑,我会自己将其包含在答案中,但没有时间...
【解决方案2】:

恐怕你不会在这里绕过一些计算。我强烈建议采用基于java.time 类的方法,但您也可以使用java.util.Calendar 类和myCalendar.get(Calendar.ZONE_OFFSET) 进行这些计算:

https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#ZONE_OFFSET

【讨论】:

    猜你喜欢
    • 2019-06-05
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 2013-04-24
    相关资源
    最近更新 更多