我必须在不同的时区使用Java 8日期/时间。例如:
LocalDateTime dateTime = LocalDateTime.of(2017, Month.JUNE, 1, 13, 39);
Instant instant = dateTime.atZone(ZoneId.of("Europe/Paris")).toInstant();
和时间帧是到dateTimes之间的实例
但我不想对时区进行硬编码,这总是一种不好的做法
我无法在Java API中找到任何常量来表示不同的时区,如https://en.m.wikipedia.org/wiki/List_of_tz_database_time_zones
是否存在短区ID中的映射?
https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html#of-java.lang.String-java.util.Map-
答案 0 :(得分:8)
时间区域经常被政治家重新定义。出现新区域。旧的重命名(例如:Asia/Kolkata
)。有些人决心实际上并不是独特的,最终指向另一个人(例如:America/Montreal
)。而这只是名称 - 每个区域内的偏移也经常被政治家修改为夏令时(DST)等异常,或决定完全退出DST或决定全年保持DST或决定将偏移量改变15分钟,以便做出一些政治声明,例如区别于邻国。所以没有简单的永久清单。
Java附带了tzdata时区数据库的副本。如果您关心的任何区域都经历了更改,则需要在Java安装中更新此tzdata。 Oracle在实现过程中为这项工作提供了一个工具;我不了解别人。同样,您还应该更新主机操作系统中的tzdata以及其他实用程序,例如Postgres等数据库。
对于Java中ZoneId
对象的引用,您可以将一些定义为常量。 java.time类是线程安全的。因此,您可以将单个实例保持为常量。
public class TimeUtils {
static public ZoneId ZONEID_EUROPE_PARIS = ZoneId.of( "Europe/Paris" ) ;
static public ZoneId ZONEID_ASIA_KOLKATA = ZoneId.of( "Asia/Kolkata" ) ;
}
您有LocalDateTime
代表潜在的时刻,而不是时间轴上的特定点。 LocalDateTime
有否时区或偏移量信息。因此今年6月1日中午的LocalDateTime
可能意味着许多不同的时刻,第一个中午发生在Kiribati,其中时区比UTC提前14个小时偏移。孟加拉国的中午来晚了,法国巴黎的中午还有几个小时。因此,在为上下文应用时区之前,LocalDateTime
没有任何实际意义。
LocalDateTime noon1June2017Anywhere = LocalDateTime.of( 2017 , Month.JUNE , 1 , 12 , 0);
在需要ZoneId
的地方使用这些常量。
ZonedDateTime noon1June2017EuropeParis = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_EUROPE_PARIS ) ;
ZonedDateTime noon1June2017AsiaKolkata = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_ASIA_KOLKATA ) ;
请注意,noon1June2017EuropeParis
和noon1June2017AsiaKolkata
两个不同的时刻,时间轴上的不同点。中午在印度比在法国发生得更早。
让我们将UTC中的这两个值视为Instant
个对象。这两个Instant
对象不相等,因为加尔各答对象比巴黎对象早几个小时。
Instant instantNoon1June2017EuropeParis = noon1June2017EuropeParis.toInstant() ; // Extract the same moment but in UTC zone.
Instant instantNoon1June2017AsiaKolkata = noon1June2017AsiaKolkata.toInstant() ; // Extract the same moment but in UTC zone.
如果您的问题的目的是外部化应用哪个区域的决定,以便您可以在不重新编译源代码的情况下更改该选择,只需存储区域名称的字符串,例如Europe/Paris
as某些外部资源中的字符串。
将您的字符串传递给ZoneId.of
。
ZoneId z = ZoneId.of( someStringOfZoneName ) ;
人们常用的可能存储机制:
ZoneId.getAvailableZoneIds
您可以要求JVM的当前默认区域:ZoneId.systemDefault
。但请注意,这可以随时由该JVM中的任何应用程序中的任何代码进行更改。