ZetCode

Java ZoneOffsetTransitionRule 类

最后修改时间:2025 年 4 月 16 日

java.time.zone.ZoneOffsetTransitionRule 类定义了时区转换的规则。它指定了夏令时在特定时区内如何变化。该类是不可变的且线程安全的。

ZoneOffsetTransitionRule 与其他时间类一起处理时区转换。它定义了转换何时发生以及转换前后适用的偏移量。这些规则通常由 ZoneRules 使用。

ZoneOffsetTransitionRule 类概述

ZoneOffsetTransitionRule 提供了创建和查询转换规则的方法。关键操作包括获取转换详细信息和计算确切的转换日期。该类处理复杂的转换规则。

public final class ZoneOffsetTransitionRule implements Serializable {
    public static ZoneOffsetTransitionRule of(
        Month month, int dayOfMonthIndicator, DayOfWeek dayOfWeek,
        LocalTime time, boolean timeEndOfDay, TimeDefinition timeDefinition,
        ZoneOffset standardOffset, ZoneOffset offsetBefore,
        ZoneOffset offsetAfter);
    public ZoneOffsetTransition createTransition(int year);
    public Month getMonth();
    public int getDayOfMonthIndicator();
    public DayOfWeek getDayOfWeek();
    public LocalTime getLocalTime();
    public boolean isMidnightEndOfDay();
    public TimeDefinition getTimeDefinition();
    public ZoneOffset getStandardOffset();
    public ZoneOffset getOffsetBefore();
    public ZoneOffset getOffsetAfter();
}

以上代码显示了 ZoneOffsetTransitionRule 提供的关键方法。这些方法允许创建和查询转换规则。该类处理复杂情况,例如三月的最后一个星期日或特定日期后的第一个星期日。

创建基本转换规则

此示例演示了如何创建简单的夏令时转换规则。该规则定义了在 3 月 31 日当地时间 01:00 发生的转换。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.MARCH, 31, null, 
            LocalTime.of(1, 0), false, 
            TimeDefinition.WALL,
            ZoneOffset.ofHours(1), 
            ZoneOffset.ofHours(1), 
            ZoneOffset.ofHours(2));
            
        System.out.println("Transition rule: " + rule);
        
        // Create transition for specific year
        ZoneOffsetTransition transition = rule.createTransition(2025);
        System.out.println("Transition in 2025: " + transition);
    }
}

此示例创建了 3 月 31 日凌晨 1 点的转换规则。时间定义为 WALL,表示当地时钟时间。偏移量从 +01:00 变为 +02:00。

创建最后一个星期日规则

此示例演示了如何为一个月中的最后一个星期日创建规则。这种模式在许多国家/地区的夏令时转换中很常见。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.OCTOBER, -1, DayOfWeek.SUNDAY,
            LocalTime.of(2, 0), false,
            TimeDefinition.WALL,
            ZoneOffset.ofHours(1),
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(1));
            
        System.out.println("Last Sunday rule: " + rule);
        
        // Calculate transition for 2025
        ZoneOffsetTransition transition = rule.createTransition(2025);
        System.out.println("Transition in 2025: " + transition);
        System.out.println("Transition date: " + transition.getDateTime());
    }
}

此规则指定 10 月最后一个星期日凌晨 2 点。dayOfMonthIndicator 为 -1,表示最后一次出现。偏移量从 +02:00 变回 +01:00。

特定日期后的第一个星期日

此示例展示了如何为特定日期后的第一个星期日创建规则。这种模式被某些时区用于夏令时转换。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.MARCH, 8, DayOfWeek.SUNDAY,
            LocalTime.of(2, 0), false,
            TimeDefinition.WALL,
            ZoneOffset.ofHours(-5),
            ZoneOffset.ofHours(-5),
            ZoneOffset.ofHours(-4));
            
        System.out.println("First Sunday after March 8 rule: " + rule);
        
        // Calculate transitions for multiple years
        for (int year = 2023; year <= 2025; year++) {
            ZoneOffsetTransition transition = rule.createTransition(year);
            System.out.println(year + " transition: " + transition.getDateTime());
        }
    }
}

此规则定义了 3 月 8 日之后的第一个星期日凌晨 2 点。偏移量从 -05:00 变为 -04:00。该示例显示了多年来的转换。

使用不同的时间定义

此示例演示了三种不同的时间定义类型:WALL、STANDARD 和 UTC。每种类型都会影响转换时间的解释方式。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        // WALL time (local clock time)
        ZoneOffsetTransitionRule wallRule = ZoneOffsetTransitionRule.of(
            Month.APRIL, 1, null,
            LocalTime.of(1, 30), false,
            TimeDefinition.WALL,
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(3));
            
        // STANDARD time (standard offset time)
        ZoneOffsetTransitionRule standardRule = ZoneOffsetTransitionRule.of(
            Month.APRIL, 1, null,
            LocalTime.of(1, 30), false,
            TimeDefinition.STANDARD,
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(3));
            
        // UTC time
        ZoneOffsetTransitionRule utcRule = ZoneOffsetTransitionRule.of(
            Month.APRIL, 1, null,
            LocalTime.of(1, 30), false,
            TimeDefinition.UTC,
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(2),
            ZoneOffset.ofHours(3));
            
        System.out.println("WALL transition: " + wallRule.createTransition(2025));
        System.out.println("STANDARD transition: " + standardRule.createTransition(2025));
        System.out.println("UTC transition: " + utcRule.createTransition(2025));
    }
}

此示例显示了不同的时间定义如何影响实际转换。WALL 使用当地时间,STANDARD 使用标准偏移时间,而 UTC 使用 UTC。

午夜结束日转换

此示例演示了在一天结束时午夜发生的转换。这需要特殊处理,因为午夜可能存在歧义。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.DECEMBER, 31, null,
            LocalTime.MIDNIGHT, true,
            TimeDefinition.WALL,
            ZoneOffset.ofHours(1),
            ZoneOffset.ofHours(1),
            ZoneOffset.ofHours(0));
            
        System.out.println("End-of-day rule: " + rule);
        
        ZoneOffsetTransition transition = rule.createTransition(2025);
        System.out.println("Transition: " + transition);
        System.out.println("Instant: " + transition.getInstant());
        System.out.println("DateTimeBefore: " + transition.getDateTimeBefore());
        System.out.println("DateTimeAfter: " + transition.getDateTimeAfter());
    }
}

此规则定义了在 12 月 31 日结束时的午夜发生的转换。timeEndOfDay 参数设置为 true。偏移量从 +01:00 变为 +00:00。

复杂转换规则

此示例结合了多个功能来创建复杂的转换规则。它使用星期几、时间定义和不同的偏移量。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.MARCH, 15, DayOfWeek.SATURDAY,
            LocalTime.of(1, 30), false,
            TimeDefinition.STANDARD,
            ZoneOffset.ofHours(-8),
            ZoneOffset.ofHours(-8),
            ZoneOffset.ofHours(-7));
            
        System.out.println("Complex rule: " + rule);
        
        // Show transitions for next 5 years
        for (int year = 2025; year <= 2029; year++) {
            ZoneOffsetTransition transition = rule.createTransition(year);
            System.out.printf("%d: %s (day %d)%n", 
                year, transition.getDateTime(), 
                transition.getDateTime().getDayOfMonth());
        }
    }
}

此规则定义了在 3 月 15 日后的第一个星期六凌晨 1:30 标准时间进行的转换。偏移量从 -08:00 变为 -07:00。该示例显示了多年来的确切日期。

查询转换规则属性

此示例演示了如何查询转换规则的各种属性。可以单独检查规则的所有组件。

Main.java
package com.zetcode;

import java.time.*;
import java.time.zone.*;

public class Main {

    public static void main(String[] args) {
        
        ZoneOffsetTransitionRule rule = ZoneOffsetTransitionRule.of(
            Month.APRIL, 10, DayOfWeek.SUNDAY,
            LocalTime.of(2, 0), false,
            TimeDefinition.WALL,
            ZoneOffset.ofHours(3),
            ZoneOffset.ofHours(3),
            ZoneOffset.ofHours(4));
            
        System.out.println("Month: " + rule.getMonth());
        System.out.println("Day of month indicator: " + rule.getDayOfMonthIndicator());
        System.out.println("Day of week: " + rule.getDayOfWeek());
        System.out.println("Local time: " + rule.getLocalTime());
        System.out.println("Time definition: " + rule.getTimeDefinition());
        System.out.println("Standard offset: " + rule.getStandardOffset());
        System.out.println("Offset before: " + rule.getOffsetBefore());
        System.out.println("Offset after: " + rule.getOffsetAfter());
        System.out.println("Is midnight end of day: " + rule.isMidnightEndOfDay());
    }
}

此示例演示了如何检查转换规则的所有属性。可以通过 getter 方法访问规则的每个组件。这对于分析或显示规则详细信息很有用。

来源

Java ZoneOffsetTransitionRule 类文档

在本文中,我们介绍了 Java ZoneOffsetTransitionRule 类的基本方法和功能。理解这些概念对于在 Java 应用程序中处理时区转换至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员,在该领域拥有多年的经验。我从 2007 年开始撰写编程文章,并撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程