我正在尝试将来自前端的值映射到ZoneId类,如下所示:

Optional.ofNullable(timeZone).map(ZoneId::of).orElse(null)

在大多数时区,它工作正常,但是,对于某些值,Java抛出异常:

java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Punta_Arenas

但是,根据IANA,这是一个有效的时区:

https://www.iana.org/time-zones

Zone America/Punta_Arenas -4:43:40 - LMT 1890

我当时正在考虑将偏移量用于此类时区(仅用于硬编码值),但我想应该有更方便的方法来解决此问题。 Java有办法解决吗?

不支持的其他时区:

美国/ Punta_Arenas

亚洲/阿特劳

亚洲/法马古斯塔

亚洲/仰光

美东时间

欧洲/萨拉托夫

HST

MST

我的Java版本:" 1.8.0_121" Java?SE运行时环境(内部版本1.8.0_121-b13)Java HotSpot?64位服务器VM(内部版本25.121-b13,混合模式)

您确切使用的是哪个Java版本; Java 8的最新更新?时区信息会随着新的Java更新而频繁更新,这可能是因为您使用的是特定的Java版本,其中未定义您所引用的Java版本。

我使用Java 8更新144(当前为最新版本)进行了尝试,它可以按预期工作。

Java版本" 1.8.0_121" Java?SE运行时环境(内部版本1.8.0_121-b13)Java HotSpot(TM)64位服务器VM(内部版本25.121-b13,混合模式)

然后更新到最新版本。

可以依靠Java版本解析时区吗?如果prod服务器使用不同的版本并进行更新,那会非常困难。他们应该提供一种更可靠的方法。

ZoneId不支持3个字母的名称(例如EST或HST),主要是因为它们是模棱两可且不是标准的-尽管您可以使用SHORT_IDS映射,该映射具有一些默认/复古兼容/有争议的映射

无论Java版本如何,都可以更新时区数据:oracle.com/technetwork/java/javase/tzupdater-readme-136440.html

@Hugo,谢谢,我喜欢那样。它比更新整个java更方便。 SHORT_IDS-好主意!

如果需要,还可以使用自己的ID映射,并在of(name, map)方法中使用它

@雨果,谢谢!写一个答案来总结所有这些怎么样? :)

我已经用Java 1.8.0_121测试过,确实缺少某些区域。

修复它的最明显方法是更新Java版本-在Java 1.8.0_131中,以上所有区域均可用-除了3个字母的名称(EST,HST等)以外,更多内容在下面。

但是我知道生产环境中的更新并不像我们想要的那么容易(也不快)。在这种情况下,您可以使用TZUpdater工具,该工具可以在不更改Java版本的情况下更新JDK的时区数据。

唯一的细节是ZoneId不能与3个字母的缩写(EST,HST等)一起使用。那是因为那些名字是模棱两可的而不是标准的。

但是,如果要使用它们,则可以使用自定义ID的映射。 ZoneId带有内置地图:

ZoneId.of("EST", ZoneId.SHORT_IDS);

问题在于SHORT_IDS映射中使用的选择-与其他选择一样-是任意的,甚至是有争议的。如果要为每个缩写使用不同的区域,只需创建自己的地图即可:

Map map = new HashMap<>();

map.put("EST","America/New_York");

... put how many names you want

System.out.println(ZoneId.of("EST", map)); // creates America/New_York

当然,只有3个字母的名称是GMT和UTC,但在这种情况下,最好使用ZoneOffset.UTC常量。

如果您无法更新Java版本,也无法运行TZUpdater工具,那么还有另一种选择(难度更大)。

您可以扩展java.time.zone.ZoneRulesProvider类,并创建一个可以创建缺少的ID的提供程序。像这样:

public class MissingZonesProvider extends ZoneRulesProvider {

private Set missingIds = new HashSet<>();

public MissingZonesProvider() {

missingIds.add("America/Punta_Arenas");

missingIds.add("Europe/Saratov");

// add all others

}

@Override

protected Set provideZoneIds() {

return this.missingIds;

}

@Override

protected ZoneRules provideRules(String zoneId, boolean forCaching) {

ZoneRules rules = null;

if ("America/Punta_Arenas".equals(zoneId)) {

rules = // create rules for America/Punta_Arenas

}

if ("Europe/Saratov".equals(zoneId)) {

rules = // create rules for Europe/Saratov

}

// and so on

return rules;

}

// returns a map with the ZoneRules, check javadoc for more details

@Override

protected NavigableMap provideVersions(String zoneId) {

TreeMap map = new TreeMap<>();

ZoneRules rules = provideRules(zoneId, false);

if (rules != null) {

map.put(zoneId, rules);

}

return map;

}

}

创建ZoneRules是最复杂的部分。

一种方法是获取最新的IANA文件并阅读它们。您可以看一下JDK源代码,看看它是如何从中创建ZoneRules的(尽管我不确定JDK中的文件是否与IANA的文件格式完全相同)。

无论如何,此链接说明了如何读取IANA的文件。然后,您可以查看ZoneRules javadoc,以了解如何将IANA信息映射到Java类。在此答案中,我创建了一个非常简单的ZoneRules,其中仅包含2个转换规则,因此您可以大致了解其操作方法。

然后,您需要注册提供者:

ZoneRulesProvider.registerProvider(new MissingZonesProvider());

现在,新区域将可用:

ZoneId.of("America/Punta_Arenas");

ZoneId.of("Europe/Saratov");

... and any other you added in the MissingZonesProvider class

还有其他使用提供程序的方法(而不是注册),请查看javadoc以获取更多详细信息。在同一javadoc中,还提供了有关如何正确实施区域规则提供程序的更多详细信息(我的上述版本非常简单,可能缺少一些详细信息,例如provideVersions的实现-它应使用提供程序的版本作为键,而不是我正在执行的区域ID等)。

当然,更新Java版本后必须立即放弃此提供程序(因为您不能有2个提供程序创建具有相同ID的区域:如果新提供程序创建的ID已存在,则在尝试时会引发异常进行注册)。

时区 java 巴黎,关于时区:Java没有有关所有IANA时区的信息相关推荐

  1. java 时区 列表_浅解 JAVA与时区

    时区转换 主要介绍一下 Java 时区转换相关的一些概念,和转换示例. 由于夏令时的存在,应该通过Java 或者 DB 提供的方法来转换. JAVA 时间的时区转换 Java Date 支持 UTC ...

  2. java 时区处理_如何使用Java处理日历时区?

    如何使用Java处理日历时区? 我有一个来自我的应用程序的Timestamp值. 用户可以在任何给定的本地TimeZone中. 由于此日期用于假定给定时间始终为GMT的WebService,因此我需要 ...

  3. 高级JAVA开发必备技能:java8 新日期时间API((一)JSR-310:ZoneId 时区和偏移量)(JAVA 小虚竹)

    技术活,该赏 点赞再看,养成习惯 大家好,我是小虚竹.之前有粉丝私聊我,问能不能把JAVA8 新的日期时间API(JSR-310)知识点梳理出来.答案是肯定的,谁让我宠粉呢.由于内容偏多(超十万字了) ...

  4. java 获取系统的时区_【转】Java 获取操作系统时区

    Java 可以通过 Timezone 获取时区,但是通过 Timezone 获取的时区是 JVM 初始化时保存的时区,并不是操作系统所设置的时区.当修改过操作系统的时区后,JVM 并不会同步更新.Ti ...

  5. Java时区处理之夏令时,冬令时 - 美国的6个时区

    在开始之前,如果要了解Java中的时区操作的基本概念和事例,可以参见另一篇博客:Java时区处理之Date,Calendar,TimeZone,SimpleDateFormat 一.夏令时概述: Da ...

  6. 【Java编程系列】Java判断世界各时区的夏令时、冬令时

    热门系列: [Java编程系列]java用POI.Itext生成并下载PPT.PDF文件 [Java编程系列]二进制如何表示小数?0.3+0.6为什么不等于0.9?纳尼!!! 程序人生,精彩抢先看 目 ...

  7. 高级JAVA开发必备技能:时区的规则发生变化时,如何同步JDK的时区规则(实战方案,建议收藏)

    技术活,该赏 点赞,收藏再看,养成习惯 场景 服务器安装JDK时,默认会有支持JDK版本对应的时区规则.但是时区规则可能会变化的,那如何保持时区规则是最新的呢? TZUpdater 工具介绍 ​ 提供 ...

  8. java simpledateformat gmt_利用SimpleDateFormat进行时间的跨时区转换 - Java

    * 次方法主要用来将特定时区的时间转换成指定时区的时间,比如将北京时间"2018-04-08 15:40:49.031",转换对应的美国东部时间是"2018-04-08 ...

  9. 如何将java.util.Date转换为java.sql.Date?

    我试图使用java.util.Date作为输入,然后用它创建一个查询-所以我需要一个java.sql.Date . 我很惊讶地发现它不能隐式或显式地进行转换-但我什至不知道该怎么做,因为Java AP ...

  10. 【Java 8系列】Java日期时间的新主宰者:LocalDate、LocalTime、LocalDateTime、ZonedDateTime

    热门系列: [Java 8系列]收集器Collector与工具类Collectors [Java 8系列]Stream详解,看这一篇就够啦 [Java 8系列]Lambda 表达式,一看就废 [Jav ...

最新文章

  1. LinkedHashMap分析
  2. glib 2.0 arm linux,为ARM编译Glib
  3. 求递推序列的第N项(51Nod-1126)
  4. mysql 建表uk_mysql建表规范
  5. 新版本到来之前,先来看看 Ubuntu 默认主题的变化吧
  6. 学生考勤及行为管理系统_幼儿园接送考勤管理系统,可抓拍陌生人 预警黑白名单!...
  7. C/C++实现荷兰国旗问题
  8. 机器学习实战-Python机器学习项目实战
  9. Android为页面添加水印
  10. 社群编码识别黑灰产攻击实践
  11. html旋转木马 代码,JavaScript实现旋转木马轮播图
  12. 网络服务器的配置与管理
  13. Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
  14. php-hyperf 使用Saber报 HTTP -4 Unknown: Linux Code 11: Resource temporarily unavailable
  15. 【Pytorch】torch.bmm()方法使用
  16. 牛客小白月赛21(求三角形的外心模板)
  17. 公路平曲线及主点桩号计算
  18. 微信小程序开发制作 | 小程序开发者工具功能介绍
  19. 切换NPM源(淘宝源)
  20. React Native 在红米手机真机调试失败

热门文章

  1. 配色方案|平板羽毛集,为你的下个作品做安排
  2. 好用到让设计师尖叫的UI设计网格素材
  3. 手机移动端APP引导界面设计模板素材,分层可临摹
  4. python调用win32_python调用win32接口进行截图
  5. CPU性能参数的含义
  6. pthread_detach():主线程与子线程分离,子线程结束后,资源自动回收
  7. (4)Linux进程调度-组调度及带宽控制
  8. oracle透明网关访问sqlserver_基于智慧照明网关的地下停车场照明解决方案
  9. firefox驱动_零适配 + 全兼容!龙芯电脑推出办公外设利旧通用解决方案:运行原生 Windows 驱动程序...
  10. Eclipse是否必需要安装jdk,jre