Skip to main content
 首页 » 编程设计

Java 8之尝试使用文本时区 ID 解析时间戳

2024年05月22日30zdz8207

呃……我这辈子都想不通。我正在使用 Java 8 并尝试做一些像解析时间戳一样简单的事情,其中​​时区 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 作为文本值出现的时间戳?

请您参考如下方法:

有两个问题:

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 不是区域的标准格式并且不受支持。您可以通过以下方式查看支持的时区:

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); 

这应该有效。