Java时区数据库与IANA数据
IANA数据库和Java tzdb.dat 2019c之间存在夏令时差异 非洲/卡萨布兰卡时区的数据库让我非常困惑。可能还有其他人,但我找到了这个。据我所知,IANA时区数据库清楚地表明摩洛哥(非洲/卡萨布兰卡)支持DST。不幸的是,2019c版本中的Java时区数据库tzdb.dat并不支持DST。这已经并将给我带来无限的悲痛。我在这里错过了什么,或者其他人看到过这种事情吗 非洲/卡萨布兰卡的IANA表2019c 注意:下表部分显示正常时间为UTC+1,日光节约时间为UTC。标准和日光缩写之间用斜线(/)分隔 区域名称STDOFF规则格式[直到] 非洲区/卡萨布兰卡-0:30:20-LMT 1913年10月26日Java时区数据库与IANA数据,java,timezone,dst,Java,Timezone,Dst,IANA数据库和Java tzdb.dat 2019c之间存在夏令时差异 非洲/卡萨布兰卡时区的数据库让我非常困惑。可能还有其他人,但我找到了这个。据我所知,IANA时区数据库清楚地表明摩洛哥(非洲/卡萨布兰卡)支持DST。不幸的是,2019c版本中的Java时区数据库tzdb.dat并不支持DST。这已经并将给我带来无限的悲痛。我在这里错过了什么,或者其他人看到过这种事情吗 非洲/卡萨布兰卡的IANA表2019c 注意:下表部分显示正常时间为UTC+1,日光节约时间为UTC。标准和日光缩写之间
0:00 Morocco +00/+01 1984 Mar 16
1:00 - +01 1986
0:00 Morocco +00/+01 2018 Oct 28 3:00
1:00 Morocco +01/+00
从2018年10月28日到目前,标准和夏令时的偏移量分别为+1和+0(斜线(/)分隔标准和夏令时缩写。)
STDOFF 1:00,因此要添加到UT以获得标准时间的时间量,而无需对夏令时进行任何调整,这对应于当前时间UTC+1。
因此,我们选择非洲/卡萨布兰卡区域,即UTC,并根据斋月添加偏移量+01/+00。”
测试
我编写了一个简单的Java类来检查2019c TZDB。这个类(如下所示)表明最新的Java时区数据文件tzdb.dat文件有问题。此测试使用IBM SR5FP40和时区2019c数据文件运行。我使用2019c数据文件获得了与OpenJDK相同的结果
tzdb.dat的第一行显示2019c
TZDB 2019cX非洲/阿比让非洲/阿克拉非洲/亚的斯亚贝巴非洲/阿尔及尔
显示问题的测试
时区=非洲/卡萨布兰卡
支持日光节约时间=false
2019年5月20日星期一00:00:00潮湿日期当前为DST false
时区名称西欧时间
时区ID非洲/卡萨布兰卡
还运行了一个基线测试,以显示是否支持DST,代码将显示它
时区=欧洲/罗马
支持日光节约时间=真
日期:2019年5月20日星期一00:00:00 CEST当前为DST true
时区名称中欧时间
时区ID欧洲/罗马
代码在这里供参考
import java.util.*;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class checkdaylight{
public static void main(String[] args)
{
// Create TimeZone object
//Europe/Rome
//Pacific/Pago_Pago
//Africa/Casablanca
String TimezoneToTest = "Africa/Casablanca";
System.out.println("Time Zone = " + TimezoneToTest);
TimeZone obj = TimeZone.getTimeZone(TimezoneToTest);
TimeZone.setDefault(TimeZone.getTimeZone(TimezoneToTest)); //to avoid confusion
// Checking day light time
// and displaying the result
System.out.println("Supports Day light Savings time = "
+ obj.useDaylightTime());
String pattern = "yyyy-MM-dd";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
try{
simpleDateFormat.setTimeZone(TimeZone.getTimeZone(TimezoneToTest));
Date checkdate = simpleDateFormat.parse("2019-05-20");
System.out.println("Date " + checkdate.toString()+ " is currently in DST "+ obj.inDaylightTime(checkdate));
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Time zone name " +obj.getDisplayName());
System.out.println("Time zone ID " + obj.getID());
}
}
摩洛哥现在永远在DST上
截至2018年10月26日,摩洛哥切换为永久†
年,政府只发出了2天通知(!)。很明显,政府打算停止所有的时钟转换,也不打算再做任何改变。本法令意味着全年抵消+01:00
这项法令还意味着摩洛哥不再“在DST上”。新的正常值是UTC前一小时的偏移量,而在旧的日子里,偏移量通常在UTC(零小时分秒的偏移量)。因此,请注意下面的代码,现在调用返回false(2020年初)
有关详细信息,请参阅维基百科:
†当我说“永久”时,请带上一个简单的句子。世界各地的政治家都表现出频繁改变各自时区偏移量的倾向。这种“永远在DST上”只是最新一种引起政客们兴趣的时尚。始终期待进一步的变化
避免遗留日期时间类
您正在使用可怕的日期时间类,这些类在几年前被JSR310中定义的现代java.time类所取代。不再有任何理由使用那些糟糕的遗留类
java.time
指定您想要的时区
ZoneId zCasablanca = ZoneId.of( "Africa/Casablanca" ) ;
获取区域规则
ZoneRules rulesCasablanca = zCasablanca.getRules() ;
询问适用于该区域特定时刻的规则
ZoneOffset offset = rulesCasablanca.getOffset( Instant.now() ) ;
boolean isDst = rules.isDaylightSavings( instant ) ;
或者把它折叠成一行
ZoneOffset offset = ZoneId.of( "Africa/Casablanca" ).getRules().getOffset( Instant.now() ) ;
验证您的Java版本
System.out.println( "Java vendor and version:" ) ;
System.out.println( " " + System.getProperty("java.vendor") ) ;
System.out.println( " " + Runtime.version() ) ;
String tzdataVersion =
java.time.zone.ZoneRulesProvider
.getVersions("UTC")
.lastEntry()
.getKey()
;
System.out.println( "tzdata: " + tzdataVersion ) ;
System.out.println( "" ) ;
请参阅此代码
Java供应商和版本:
甲骨文公司
12.0.1+12
tzdata:2018g
offset.toString():+01:00
isDst:错误
具体日期
让我们试试你的具体日期
LocalDate localDate = LocalDate.parse( "2019-05-20" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;
System.out.println( "zdt.toString(): " + zdt ) ;
System.out.println(
"offset: " + rules.getOffset( zdt.toInstant() ) +
" | is in DST: " + rules.isDaylightSavings( zdt.toInstant() )
);
zdt.toString():2019-05-20T00:00+01:00[非洲/卡萨布兰卡]
偏移量:+01:00 |在DST中:假
tzdata
Oracle将文件内置到Java运行时中
该列表显示,摩洛哥切换到永久DST的原因在tzdata2018g
中。该tzdata文件与Java版本11.0.2、8u201和7u211捆绑在一起。至少Oracle捆绑了它,而我认为项目也捆绑了它(我没有验证)
摩洛哥于2018年10月27日切换至永久+01
摩洛哥从2018年10月27日起从+00/+01切换到永久+01,因此其时钟不会像之前计划的那样在2018年10月28日回落
要获取JVM正在使用的tzdata数据文件的版本,请参阅问题的
关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,& 要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是 该项目现已启动,建议迁移到类 您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*
类
从哪里获得java.time类
- 、和更高版本-标准Java API的一部分,带有捆绑实现。
- Java9添加了一些次要功能和修复
- 及
- 大多数java.time功能都在中向后移植到Java6和Java7
-
- 更高版本的Android捆绑包实现了java.time类
- 对于早期的Android(没有回答您的问题,我建议您不要使用
时区
和SimpleDateFormat
。这些类设计糟糕且过时很久,日期
特别麻烦。相反,请使用<SimpleDateFormat