Java 为什么负DST时间有标准区域名称?
对于DST偏移量为负的特定历史日期,我得到了错误的时区名称 时区数据库(tzdata)的更新在1946-12-01至1947-02-23期间为欧洲/布拉格引入了负DST 这是欧洲/布拉格的数据来源:Java 为什么负DST时间有标准区域名称?,java,timezone,Java,Timezone,对于DST偏移量为负的特定历史日期,我得到了错误的时区名称 时区数据库(tzdata)的更新在1946-12-01至1947-02-23期间为欧洲/布拉格引入了负DST 这是欧洲/布拉格的数据来源: # We know of no English-language name for historical Czech winter time; # abbreviate it as "GMT", as it happened to be GMT. 这个新数据库是从u181开始使用Java8的 当
# We know of no English-language name for historical Czech winter time;
# abbreviate it as "GMT", as it happened to be GMT.
这个新数据库是从u181开始使用Java8的
当在指定时间段内使用时间时,我得到了错误的时区名称“CET”/“中欧时间”,而不是tzdata中所述的GMT
Long timeInMilis = Long.parseLong("-725328000000");
String pattern = "yyyy-MM-dd HH:mm:ss zzz";
TimeZone.setDefault(TimeZone.getTimeZone(("Europe/Berlin")));
System.out.println(new SimpleDateFormat(pattern).format(new Date(timeInMilis)));
TimeZone.setDefault(TimeZone.getTimeZone(("Europe/Prague")));
System.out.println(new SimpleDateFormat(pattern).format(new Date(timeInMilis)));
结果是
1947-01-07 01:00:00 CET
1947-01-07 00:00:00 CET
第一排是柏林时区,第二排是布拉格。
两人都说这是CET,但对布拉格来说这是错误的。它应该是GMT,正如时区数据库中提到的,至少就我在OpenJDK发行历史中所看到的那样 …到目前为止,OpenJDK通过使用tzdata的“后保护”版本避免了处理负DST,该版本没有负DST(这一选项显然很快就会消失) 我怀疑Oracle的Java到目前为止也一直在避免处理负面DST 无论如何,我认为Java的时区实现不能很好地处理这些时区缩写。我尝试了以下示例代码:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
format.setTimeZone(TimeZone.getTimeZone(("Europe/Prague")));
for (int date = 1; date <= 28; ++date) {
System.out.println(format.format(new GregorianCalendar(1947, 1, date, 0, 0).getTime()));
}
如果我没记错的话,Java的时区实现根本不保留这些缩写变化的历史记录,它只是为时区偏移量的变化编码转换时间。显示的缩略语是根据当前而非历史标准呈现的
编辑:我以前读错了tzdata,对它的意思误解了 原因可能是区域名称不是直接取自tzdata中的适用行,而是取自TimeZone对象,它不知道日期是什么。如果您认为这种行为是错误的,那么您可能需要提交一个bug-尽管它很可能只针对
java.time
类进行修复。请注意Long.parseLong(“-725328000000”)
应该写成-725328000000L
。或者更好的是725_328_000_000L
(也可以是@VGR)我建议您不要使用时区
、简化格式
和日期
。这些类设计得很糟糕,而且很早就过时了,SimpleDateFormat
尤其是出了名的麻烦。而是使用Instant
、ZoneId
、ZonedDateTime
和DateTimeFormatter
,所有这些都来自。
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
format.setTimeZone(TimeZone.getTimeZone(("Europe/Prague")));
for (int date = 1; date <= 28; ++date) {
System.out.println(format.format(new GregorianCalendar(1947, 1, date, 0, 0).getTime()));
}
...
1947-02-20 05:00:00 CET
1947-02-21 05:00:00 CET
1947-02-22 05:00:00 CET
1947-02-23 06:00:00 CET
1947-02-24 06:00:00 CET
1947-02-25 06:00:00 CET
1947-02-26 06:00:00 CET
...