Java时区数据库与IANA数据

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。标准和日光缩写之间

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日

         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
      特别麻烦。相反,请使用<