ZetCode

Java ZoneOffset 类

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

java.time.ZoneOffset 类表示 UTC/格林威治时间的固定时区偏移量。 它用于处理时区在小时、分钟和秒上的差异。 ZoneOffset 是不可变的且线程安全的。

ZoneOffset 通常与 OffsetDateTime 等其他日期时间类一起使用。 它支持从 +18:00 到 -18:00 的偏移量。 该类为常见的偏移量(如 UTC)提供了常量。

ZoneOffset 类概述

ZoneOffset 提供了创建和操作固定时区偏移量的方法。 关键操作包括解析字符串、比较偏移量以及获取总偏移秒数。 该类处理夏令时转换。

public final class ZoneOffset implements ZoneId, TemporalAccessor,
    TemporalAdjuster, Comparable<ZoneOffset>, Serializable {
    public static final ZoneOffset UTC;
    public static ZoneOffset of(String offsetId);
    public static ZoneOffset ofHours(int hours);
    public static ZoneOffset ofHoursMinutes(int hours, int minutes);
    public static ZoneOffset ofHoursMinutesSeconds(int hours, int minutes, int seconds);
    public static ZoneOffset ofTotalSeconds(int totalSeconds);
    public int getTotalSeconds();
    public String getId();
    public boolean equals(Object obj);
}

上面的代码显示了 ZoneOffset 提供的关键方法。 这些方法允许创建和使用固定时区偏移量。 UTC 常量表示与格林威治时间的零偏移量。

创建 ZoneOffset 对象

可以通过多种方式创建 ZoneOffset 对象。 最常用的方法是 of 用于字符串解析,以及用于特定偏移量的工厂方法。 UTC 常量也可用。

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {
        
        // UTC constant
        ZoneOffset utc = ZoneOffset.UTC;
        System.out.println("UTC offset: " + utc);
        
        // From string
        ZoneOffset offset1 = ZoneOffset.of("+02:00");
        System.out.println("+02:00 offset: " + offset1);
        
        // From hours
        ZoneOffset offset2 = ZoneOffset.ofHours(5);
        System.out.println("+05:00 offset: " + offset2);
        
        // From hours and minutes
        ZoneOffset offset3 = ZoneOffset.ofHoursMinutes(5, 30);
        System.out.println("+05:30 offset: " + offset3);
        
        // From total seconds
        ZoneOffset offset4 = ZoneOffset.ofTotalSeconds(3600);
        System.out.println("+01:00 offset (from seconds): " + offset4);
    }
}

此示例演示了创建 ZoneOffset 对象的不同方法。 输出显示了各种时区偏移量。 请注意,字符串格式必须遵循 ISO-8601 时区指示符模式。

获取偏移信息

ZoneOffset 可以提供以秒为单位的总偏移量及其字符串 ID。 这些值对于计算和显示目的非常有用。 这些方法提供了对偏移量基本属性的访问。

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset = ZoneOffset.of("+05:30");
        
        // Get total offset in seconds
        int totalSeconds = offset.getTotalSeconds();
        System.out.println("Total seconds: " + totalSeconds);
        
        // Get ID string
        String id = offset.getId();
        System.out.println("ID: " + id);
        
        // Calculate hours and minutes
        int hours = totalSeconds / 3600;
        int minutes = (totalSeconds % 3600) / 60;
        System.out.printf("Human-readable: %+02d:%02d%n", hours, minutes);
    }
}

此示例显示了如何从 ZoneOffset 中提取信息。 getTotalSeconds 方法返回以秒为单位的完整偏移量。 ID 遵循 ISO-8601 格式的时区偏移量。

比较 ZoneOffset

可以比较 ZoneOffset 以确定它们相对于 UTC 的相对位置。 该类提供了 equalscompareTo 方法。 这些比较对于按时区排序或分组很有用。

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset1 = ZoneOffset.of("+02:00");
        ZoneOffset offset2 = ZoneOffset.of("+05:30");
        ZoneOffset offset3 = ZoneOffset.of("-03:00");
        
        // Equality check
        ZoneOffset sameOffset = ZoneOffset.ofHours(2);
        System.out.println("Equals check: " + offset1.equals(sameOffset));
        
        // Comparison
        System.out.println("Compare +02:00 and +05:30: " + 
            offset1.compareTo(offset2));
        System.out.println("Compare +02:00 and -03:00: " + 
            offset1.compareTo(offset3));
        
        // Sorting example
        System.out.println("Is +02:00 before +05:30? " + 
            (offset1.compareTo(offset2) < 0));
    }
}

此示例演示了比较 ZoneOffset 对象的各种方法。 比较基于与 UTC 的总秒数。 请注意,相等的偏移量始终具有相同的字符串表示形式。

将 ZoneOffset 与其他类一起使用

ZoneOffset 通常与 OffsetDateTime 等其他日期时间类一起使用。 这些组合允许表示具有特定偏移量的日期时间值。 在 Java Time API 中,集成是无缝的。

Main.java
package com.zetcode; 

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset = ZoneOffset.of("+05:30");
        
        // Create OffsetDateTime with offset
        OffsetDateTime odt = OffsetDateTime.now(offset);
        System.out.println("Current date-time with offset: " + odt);
        
        // Convert LocalDateTime to OffsetDateTime
        LocalDateTime ldt = LocalDateTime.now();
        OffsetDateTime odt2 = ldt.atOffset(offset);
        System.out.println("Local date-time with offset: " + odt2);
        
        // Extract offset from OffsetDateTime
        ZoneOffset extractedOffset = odt.getOffset();
        System.out.println("Extracted offset: " + extractedOffset);
    }
}

此示例显示了 ZoneOffset 如何与其他日期时间类一起工作。 atOffset 方法将偏移量附加到本地日期时间。 所有操作都保留了所表示的确切时间。

处理最大和最小偏移量

ZoneOffset 支持从 +18:00 到 -18:00 的偏移量。 尝试在此范围之外创建偏移量会引发异常。 该类验证所有输入值。

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        // Maximum offset
        ZoneOffset maxOffset = ZoneOffset.of("+18:00");
        System.out.println("Maximum offset: " + maxOffset);
        
        // Minimum offset
        ZoneOffset minOffset = ZoneOffset.of("-18:00");
        System.out.println("Minimum offset: " + minOffset);
        
        try {
            // Invalid offset (too large)
            ZoneOffset invalid = ZoneOffset.of("+19:00");
        } catch (Exception e) {
            System.out.println("Caught exception: " + e.getMessage());
        }
        
        // Edge case in seconds
        ZoneOffset edgeCase = ZoneOffset.ofTotalSeconds(18 * 3600);
        System.out.println("Edge case offset: " + edgeCase);
    }
}

此示例演示了 ZoneOffset 的有效范围。 该类严格执行 +18:00 到 -18:00 的限制。 所有工厂方法都执行此验证。

ZoneOffset vs ZoneId

ZoneOffset 与 ZoneId 的不同之处在于,它表示固定偏移量与完整的时区规则。 ZoneOffset 更简单,但不处理夏令时。 ZoneId 更灵活,但也更复杂。

Main.java
package com.zetcode; 

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {

    public static void main(String[] args) {

        // ZoneOffset example
        ZoneOffset offset = ZoneOffset.of("+02:00");
        System.out.println("Fixed offset: " + offset);
        
        // ZoneId example
        ZoneId zone = ZoneId.of("Europe/Paris");
        System.out.println("Full time zone: " + zone);
        
        // Both can be used with ZonedDateTime
        ZonedDateTime zdt1 = ZonedDateTime.now(offset);
        System.out.println("With offset: " + zdt1);
        
        ZonedDateTime zdt2 = ZonedDateTime.now(zone);
        System.out.println("With zone: " + zdt2);
        
        // ZoneOffset is a ZoneId
        System.out.println("Is ZoneOffset a ZoneId? " + 
            (offset instanceof ZoneId));
    }
}

此示例比较了 ZoneOffset 和 ZoneId 的用法。 虽然两者都可以用作 ZoneId,但 ZoneOffset 仅提供固定偏移量。 ZoneId 处理夏令时和历史变化。

来源

Java ZoneOffset 类文档

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

作者

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

列出所有Java教程