【问题标题】:Java 8 - Trying to parse timestamp with textual TimeZone IDJava 8 - 尝试使用文本时区 ID 解析时间戳
【发布时间】:2019-05-31 22:58:30
【问题描述】:

呃……我这辈子都想不通。我正在使用 Java 8 并尝试做一些简单的事情,例如解析时间戳,其中 TimeZone ID 是文本值,例如 HST:

有效

ZonedDateTime timestamp = ZonedDateTime.parse("2018-10-29T12:00:12.456-10:00");

不工作

ZonedDateTime timestamp = ZonedDateTime.parse("2018-10-29T12:00:12.456HST");

并得到这个错误:

java.time.format.DateTimeParseException: Text '2018-10-29T12:00:12.456HST' could not be parsed at index 23

有谁知道如何解析时区 ID 作为文本值出现的时间戳?

【问题讨论】:

标签: java timestamp timezone zoneddatetime


【解决方案1】:

有两个问题:

1) ZonedDateTime.parse 方法仅解析符合 ISO_ZONED_DATE_TIME 格式的字符串,您可以在此处找到有关其外观的描述: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_ZONED_DATE_TIME

为了解析您的格式,您必须创建自己的 dateTimeFormatter。

这个格式化程序看起来像这样

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendZoneId()
            .toFormatter();

如果您使用 GMT、UTC 等标准区域,则此格式化程序可以工作。 问题是 HST 不是 Zone 的标准格式并且不受支持。您可以通过以下方式查看支持的时区:

System.out.println(ZoneId.getAvailableZoneIds());

如果您仍想使用 HST 区域,您必须为您的自定义区域添加 ZoneRulesProvider,如下所示:

  ZoneRulesProvider.registerProvider(new ZoneRulesProvider() {
        @Override
        protected Set<String> provideZoneIds() {
            return Collections.singleton("HST");
        }

        @Override
        protected ZoneRules provideRules(String zoneId, boolean forCaching) {
            return ZoneRules.of(ZoneOffset.ofHours(10));
        }

        @Override
        protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) {
            TreeMap map =  new TreeMap<>();
            map.put("HST",ZoneRules.of(ZoneOffset.ofHours(10)));
            return  map;
        }
    });

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendZoneId()                
            .toFormatter();

    ZonedDateTime timestamp = ZonedDateTime.parse("2018-10-29T12:00:12.456HST", formatter);
    System.out.println(timestamp);

这应该可行。

【讨论】:

  • 这里似乎支持 HST,并且似乎是 Pacific/Honolulu 的同义词。
  • 你可以使用 HST,但是 Java ZoneId 不支持 HST,因为它是非标准的,更多信息你可以在这里找到:stackoverflow.com/questions/18405262/…。 Java 期望将整个字符串“Pacific/Honolulu”用作 ZoneId,如果您想使用 HST 作为 ZoneId,您必须注册自己的 ZoneRulesProvider
  • 对。它不是 ZoneId。但这是一个公认的区域名称。只需使用DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz")允许解析字符串。
  • 不错,更好的解决方案。
  • HSTdeprecated as an identifier。请参阅Hawaii–Aleutian Time Zone。理想情况下,应该教育发布这些字符串的发布者使用正确的时区名称,例如Pacific/Honolulu
猜你喜欢
  • 2021-07-25
  • 2020-01-05
  • 1970-01-01
  • 2014-11-02
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
相关资源
最近更新 更多