【问题标题】:Determine dates of DST switch (both forwards and backwards) for a timezone in Java?确定Java中时区的DST切换日期(向前和向后)?
【发布时间】:2011-12-24 14:46:53
【问题描述】:

我知道您可以检查Date 是否为inDaylightTime,但我如何确定该日期何时(或是否)切换到夏令时?我可以每天迭代并检查它是否在DaylightTime,但是有没有更清洁的解决方案/方法?

【问题讨论】:

    标签: java datetime date dst


    【解决方案1】:

    我建议使用Joda Time - 它的DateTimeZone 类有nextTransitionpreviousTransition 方法。

    请注意,除 DST 之外的其他原因可能会发生转换 - 标准时间的更改,或者可能是区域间隔名称的更改。但无论如何,这就是你会发现的方式:)

    (老实说,Joda Time 是一个更好的日期和时间库。)

    【讨论】:

    • +1 我很想使用不同的库,但我应该提到我正在使用遗留代码并且必须使用 Java Date 和 DateTime :-\
    • @GrailsDev:即使你不打算在其他地方使用 Joda Time,你能不能不介绍它即使是这一点? (我看不到任何可以让您在 Java 标准类中进行转换的东西,即使是 SimpleTimeZone。)
    • 我想我可以...想知道在默认 Java 类中是否有可能。
    • @GrailsDev:我看不到。不过,Joda Time 可以很容易地从 Java Date 转换。也许你可以在整个项目中悄悄地介绍它;)
    • 不使用 Joda 有什么办法吗? Java 版本低于 8。
    【解决方案2】:

    java.time

    java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

    另外,下面引用的是来自home page of Joda-Time的通知:

    请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。

    使用现代日期时间 API java.time 的解决方案: 使用 ZoneRules#nextTransitionZoneRules#previousTransition

    演示:

    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.zone.ZoneRules;
    
    public class Main {
        public static void main(String[] args) {
            Instant now = Instant.now();
            ZoneRules zoneRules = ZoneId.of("Europe/London").getRules();
    
            System.out.println(zoneRules.nextTransition(now));
    
            System.out.println(zoneRules.previousTransition(now));
        }
    }
    

    输出:

    Transition[Overlap at 2021-10-31T02:00+01:00 to Z]
    Transition[Gap at 2021-03-28T01:00Z to +01:00]
    

    ONLINE DEMO

    你可以理解following images的输出:

    从图中可以看出,2021 年 3 月 28 日,00:59 之后,时间变为 02:00,即当晚没有 01:00。有没有办法在过渡发生之前知道当地时间和区域偏移?请查看ZoneOffsetTransition 或以下演示以获得答案。

    转换前的本地时间和时区偏移量是多少?

    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.zone.ZoneOffsetTransition;
    
    public class Main {
        public static void main(String[] args) {
            ZoneId zoneId = ZoneId.of("Europe/London");
            ZoneOffsetTransition nextTransition = zoneId.getRules().previousTransition(Instant.now());
            System.out.println("Local date-time before the transition: " + nextTransition.getDateTimeBefore());
            System.out.println("Zone offset before the transition: " + nextTransition.getOffsetBefore());
        }
    }
    

    输出:

    Local date-time before the transition: 2021-03-28T01:00
    Zone offset before the transition: Z
    

    ONLINE DEMO

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。


    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport 将大部分 java.time 功能反向移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 2023-03-06
      • 1970-01-01
      • 2017-05-02
      • 2019-03-06
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多