【问题标题】:Offset is not set for few time zone in java在java中没有为几个时区设置偏移量
【发布时间】:2019-11-20 12:39:21
【问题描述】:

我想从用户那里获取时间和时区并创建一个条目。在日历 API 下使用来执行此操作,它适用于少数时区而不适用于少数时区

calendar.setTime(eventFormEntryBean.getStartDate());
TimeZone timeZone = TimeZone.getTimeZone("Europe/Amsterdam");
calendar.setTimeZone(timeZone);

工作时区(末尾+xx:xx)

  • 太平洋/帕劳 2019-11-27T20:51:09.000+09:00
  • IST - 2019-11-20T22:00:00.000+05:30
  • 欧洲/阿姆斯特丹 - 2019-11-28T12:49:24.000+01:00
  • 美国/洛杉矶 - 2019-11-20T21:32:49.000-08:00

非工作时区:-

  • 非洲/达喀尔 - 2019-11-21T05:30:45.000Z
  • 伦敦(欧洲/伦敦)- 2019-11-21T12:08:42.000Z

上述伦敦和非洲/达喀尔时区没有任何指示符来区分时区,只是在末尾指定“.000Z”。为了获得完整的时区,我们需要设置任何属性吗? .000z 是什么意思?

【问题讨论】:

  • 两个“违规”时区与 GMT 的偏移量均为 0。所以这似乎是按要求工作。 Z 基本上就是+00:00。此外,一般来说,时区偏移(例如+09:00)和时区(例如Pacific/Palau)之间没有1:1 的关系。许多不同的时区可以具有相同的偏移量,并且给定时区的偏移量可能会在一年中发生变化(感谢夏令时)。
  • CalendarTimeZone 类都设计得很糟糕而且已经过时了。我建议不要使用那些你使用 java.time,现代 Java 日期和时间 API。你需要ZoneIdZonedDateTime

标签: java jakarta-ee calendar


【解决方案1】:

如果您希望能够编写反映偏移量和时区差异的代码,请离开 java.util 并切换到 java.time(对于 Java 8+ 和 support library for Java 6 and 7)。

然后您可以执行以下操作:

public static void main(String[] args) {
    /*
     * the base of this example is a date time with an offset of +01:00
     * (which is present in several zones, not just in Europe/Amsterdam!)
     */
    String datetime = "2019-11-28T12:49:24.000+01:00";
    // parse it to an offset-aware object
    OffsetDateTime plusOneHourOffsetDateTime = OffsetDateTime.parse(datetime);
    // print it to be sure ;-)
    System.out.println(plusOneHourOffsetDateTime
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
    // convert it to a zone-aware date time object by providing the zone
    ZonedDateTime europeAmsterdamZonedDateTime = plusOneHourOffsetDateTime
            .atZoneSameInstant(ZoneId.of("Europe/Amsterdam"));
    // print it
    System.out.println(europeAmsterdamZonedDateTime
            .format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    // then take the same instant but use a different time zone
    ZonedDateTime utcZonedDateTime = plusOneHourOffsetDateTime
            .atZoneSameInstant(ZoneId.of("UTC"));
    // print that, it adds a Z (indicating an offset of 00:00) and the time zone
    // that was specified
    System.out.println(utcZonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    // take a totally different time zone and do it again
    ZonedDateTime pacificPalauZonedDateTime = plusOneHourOffsetDateTime
            .atZoneSameInstant(ZoneId.of("Pacific/Palau"));
    // print that one, too
    System.out.println(pacificPalauZonedDateTime
            .format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

输出这个

2019-11-28T12:49:24+01:00
2019-11-28T12:49:24+01:00[Europe/Amsterdam]
2019-11-28T11:49:24Z[UTC]
2019-11-28T20:49:24+09:00[Pacific/Palau]

编辑

您的评论中提到DateTimeParseException 的原因是日期时间String,因为它没有区域或偏移量,这使得它在OffsetDateTime.parse(String datetime) 中使用的默认DateTimeFormatter 无法解析.

如果您有一个带有日期和时间信息但没有区域或偏移量的String,您可以先将其解析为LocalDateTime,然后从中创建一个ZonedDateTime

public static void main(String[] args) {
    // date time String without zone or offset information
    String dateTimeString = "2019-11-30T19:35:06";
    // create a LocalDateTime from the String
    LocalDateTime ldt = LocalDateTime.parse(dateTimeString);
    // then create a ZonedDateTime from the LocalDateTime adding a zone
    ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault()); // system default here
    // and print it
    System.out.println(zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

【讨论】:

  • deHaar,我收到 DateTimeParseException。实际上我想格式化“2019-11-30T19:35:06”你能告诉我们如何解析这个吗?
  • 很棒的德哈尔,非常感谢。我们可以在 LocalDateTime 类中传递日期对象吗?
  • 我刚刚创建了独立的 java 类来测试这种行为。我实时获取日期对象,我想将它传递给 LocalDateTime 类。有没有办法设置?
  • @Anderson 是的,你可以...见this question
  • 感谢您将我导航到正确的位置。是的,转换为 LocalDateTime 但不知何故时间变了,这就是我所说的 ZonedDateTime Zdate = dateObject.toInstant().atZone(ZoneId.of(“Europe/London”)); // 我通过的日期是 Fri Nov 22 03:00:00 IST 2019 但输出时间是 2019-11-21T21:30:00Z 知道吗?
【解决方案2】:

你误会了。 Z 的含义与+00:00 完全相同,并且是以您正在生成的 ISO 8601 格式编写它的常规和推荐方式。因此,对于您的所有时区,您都获得了正确的 UTC 偏移量(可能是 IST 除外;这可能代表爱尔兰夏令时间或以色列标准时间,在这种情况下,您的 +05:30 偏移量是错误的;不要依赖模棱两可三个字母的 tome zone 缩写)。

CalendarTimeZone 类都设计得很糟糕并且已经过时了。我建议不要使用那些你使用 java.time,现代 Java 日期和时间 API。你需要ZoneIdZonedDateTime。请参阅 deHaar 的答案。

【讨论】:

    猜你喜欢
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多