当前位置: 首页 > 知识库问答 >
问题:

Java 上的日历不适用于“美国/圣地亚哥”夏令时时区

梅逸清
2023-03-14

我有一个日历对象的问题,它没有显示美国/圣地亚哥时区的DST(每日节约时间)的正确偏移:我的示例代码:time zone from time zone = time zone . gettimezone("美国/圣地亚哥");

    // Get a Calendar instance using the default time zone and locale.
    Calendar calendar = Calendar.getInstance();

    // Set the calendar’s time with the given date
    calendar.setTimeZone(fromTimeZone);

    calendar.set(Calendar.YEAR, 2015); // 2015
     calendar.set(Calendar.MONTH, 2); // Mar
     calendar.set(Calendar.DATE, 31); // 31

    calendar.set(Calendar.HOUR_OF_DAY, 7);
    calendar.set(Calendar.MINUTE, 45);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    System.out.println("offset: " + fromTimeZone.getOffset(calendar.getTimeInMillis())/(TimeUnit.MINUTES.toMillis(1)*60));

输出为:偏移量:-4在2015年3月31日的美国/圣地亚哥时区,偏移量应为-3。(参考:http://www.timeanddate.com/worldclock/converted.html?iso=20150331T00

为什么日历在这种情况下得到正确的偏移量?我用其他时区进行了测试,它在 DST 时间工作正常。

谢谢。

共有3个答案

耿锦
2023-03-14

关于您需要在JVM中保持tzdata最新,其他答案是正确的。

此外,您使用的日期时间类现在已经过时,被现代java所取代。JSR 310中定义的时间类。

ZoneId z = ZoneId.of( "America/Santiago" ) ;
LocalDate ld = LocalDate.of( 2015 , Month.MARCH , 31 ) ;
LocalTime lt = LocalTime.of( 7 , 45 , 0 , 0 ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

将该时刻调整为UTC。时间线上的同一点,不同的挂钟时间。

Instant instant = zdt.toInstant() ;

获取该时区的规则,即Zone规则对象。

ZoneRules rules = z.getRules() ;

质疑规则。获取当时使用的offset-from-UTC,由< code>ZoneOffset类表示。

ZoneOffset offset = rules.getOffset( instant ) ;

询问该地区当时是否实行夏令时(DST)。请注意Java团队在命名该方法时使用的常见拼写错误(“Saving”应该是单数)。

boolean isDst = rules.isDaylightSavings( instant ) ;

如果在DST中,则将DST调整的量作为Dation对象获取。Dation::toString方法以标准ISO 8601格式报告其值(小时、分钟和秒的数量)。例如,PT1H表示1小时。

if( isDst ) {
    Duration d = getDaylightSavings​( instant ) ;
}

请参阅此代码在 IdeOne.com 实时运行。

zdt = 2015-03-31T07:45-03:00[America/Santiago]
instant = 2015-03-31T10:45:00Z
offset = -03:00
isDst = true
d = PT1H
阎庆
2023-03-14

如果没有有关时区数据基础版本的额外信息,很难说出确切的原因是什么。但是,您的最后一条评论

根本原因是:我的系统上的JDK是1.7版本,所以在这种情况下,日历没有得到正确的时间。我尝试了jdk 1.8,然后得到了预期的输出

告诉我你显然对任何分析都不感兴趣。所以我更新这个答案给那些只想要一个解决方案而不需要知道为什么这个解决方案有效的用户。

如果html" target="_blank">用户在获取正确的时区偏移时遇到问题,那么原因通常是使用过时的数据。由于时区数据内置在底层JDK中(如果Java-8与否并不重要),您可以作为急救措施:

>

  • 将JVM更新到最新版本(也就是:最新的次要版本,实际上是Java 8u45)。

    如果这没有帮助,那么使用最新版本的TZUpdater-Tool来更新JVM的时区数据——使用预构建的数据。

    如果这仍然没有帮助,那么你可以从TZUpdater-Tool的2.0版本开始,使用该工具直接利用原始IANA/TZDB版本的最新版本来更改时区数据(感谢马特·约翰逊评论中的信息)。请记住,在IANA托管的新TZDB版本的发布和Oracle-Java-release-schedules之间总是有一个时间差。

    如果您不想依赖Oracles发布计划或TZUpdater工具,那么您可以使用一个内置时区库的外部库,它让您有机会尽快自己更新它(我知道至少有2-3个这样的库,但这里不会给出任何具体的建议。然而做适当的研究是容易的)。

  • 云煌
    2023-03-14

    智利通常在三月从夏令时转为标准时,所以你的约会通常是在标准时间。然而,自2010年以来,转换一直在4月进行(除了2011年在5月),2015年,智利宣布将停止转换,并永久保持夏令时。(编辑:智利已经撤销了2015年的决定,那一年是智利唯一没有回落到标准时间的一年。)

    因此,我认为问题很可能是您的zoneinfo数据库非常过时。如果您运行的JVM的副本不是最新的,或者您运行的是从操作系统获取分区信息数据的JVM副本(这在某些Linux发行版上发生),并且您的操作系统没有保持最新,或者您正在运行的操作系统不再接收更新,则可能会发生这种情况。

    无论如何,Java的解决方案通常是更新到最后一个JVM。

     类似资料:
    • 我得到一个格式为yyyy-MM-dd HH: mm的字符串,它代表UTC中的日期和时间。下一步是将其放入日历(带时间区UTC)。 此外,还需要创建一个单独的日历,将UTC转换为“欧洲/伦敦”时区(GMT/BST)。 之后,我需要能够检测“欧洲/伦敦”日历是否有DST(日光节约补偿)。 下面的代码将告诉你我已经走了多远,它在一台默认系统时区为GMT的英国计算机上运行正常。但是,当我在一台时区为UTC

    • 2018-03-26 09:04:14Z 2018-03-26 14:34:14+05:30 2018-03-26 11:04:14+02:00

    • 问题内容: 我想知道用Java最简单的方法来获取将来的夏令时将改变的日期列表。 一种相当灵活的方法是简单地迭代一整年的时间,然后对它们进行TimeZone.inDaylightTime()测试。这将起作用,并且我不担心效率,因为这仅在我的应用每次启动时都需要运行,但是我想知道是否有更简单的方法。 如果您想知道为什么要这样做,那是因为我有一个javascript应用程序,该应用程序需要处理包含UTC

    • 从“GMT夏令时”或任何其他可用的Windows时区信息有什么方法可以到达BST吗?

    • 问题内容: SQL Server作业/计划-美国与英国夏令时调整 我们有一台基于英国的服务器,需要在16:30(美国中部时间-这可能很奇怪,但这是由于某些数据的可用性)运行SQL Agent Job。通常这不会造成问题,因为英国和美国之间的时差为6个小时,因此我们将工作安排在22:30进行。 但是,由于英美两国在3月和11月的不同时间调整时钟以节省夏令时,因此英美之间的时差为5个小时,为2周。 我

    • 轻触方格启用设定,即可将夏令时反映于时间显示中。