ZetCode

Java ChronoZonedDateTime 接口

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

java.time.chrono.ChronoZonedDateTime 接口表示在任意历法中带有时区的日期时间。它将时间信息与时区规则相结合。该接口扩展了 ComparableTemporal

ChronoZonedDateTime 是不可变的且线程安全的。它根据特定日历系统的规则处理日期时间计算。该接口通过历法机制支持 ISO 和非 ISO 日历系统。

ChronoZonedDateTime 接口概述

该接口提供了访问日期时间字段、执行计算以及在时区之间转换的方法。它结合了历法、本地日期时间及时区信息。所有实现都必须是不可变的并且是线程安全的。

public interface ChronoZonedDateTime<D extends ChronoLocalDate>
    extends Comparable<ChronoZonedDateTime<?>>, Temporal {
    ZoneId getZone();
    ChronoLocalDateTime<D> toLocalDateTime();
    Chronology getChronology();
    boolean isBefore(ChronoZonedDateTime<?> other);
    boolean isAfter(ChronoZonedDateTime<?> other);
    ChronoZonedDateTime<D> withZoneSameInstant(ZoneId zone);
    ChronoZonedDateTime<D> withZoneSameLocal(ZoneId zone);
    long toEpochSecond();
    Instant toInstant();
}

以上代码展示了 ChronoZonedDateTime 的关键方法。这些方法允许在不同的日历系统中处理日期时间值。该接口提供精确到纳秒的精度,并具有时区感知能力。

创建 ChronoZonedDateTime 对象

ChronoZonedDateTime 对象通常通过工厂方法创建。最常用的方法是使用 ZonedDateTime,它为 ISO 日历系统实现了此接口。

Main.java
package com.zetcode;

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.chrono.ChronoZonedDateTime;

public class Main {

    public static void main(String[] args) {
        
        // Current date-time with timezone
        ChronoZonedDateTime<?> now = ZonedDateTime.now();
        System.out.println("Current zoned date-time: " + now);
        
        // Specific date-time with timezone
        ChronoZonedDateTime<?> specific = ZonedDateTime.of(
            2025, 6, 15, 14, 30, 0, 0, ZoneId.of("Europe/Paris"));
        System.out.println("Specific zoned date-time: " + specific);
        
        // From string
        ChronoZonedDateTime<?> parsed = ZonedDateTime.parse(
            "2025-01-01T12:00:00+01:00[Europe/Berlin]");
        System.out.println("Parsed zoned date-time: " + parsed);
    }
}

此示例演示了创建 ChronoZonedDateTime 对象的不同方法。输出显示了带有时区信息的日期时间值。所有示例都通过 ZonedDateTime 实现使用 ISO 日历系统。

访问日期时间组件

ChronoZonedDateTime 提供了访问其组件(包括日期、时间和时区)的方法。这些方法允许检查完整的时态状态。这些值特定于所使用的历法。

Main.java
package com.zetcode;

import java.time.ZonedDateTime;
import java.time.chrono.ChronoZonedDateTime;

public class Main {

    public static void main(String[] args) {
        
        ChronoZonedDateTime<?> zdt = ZonedDateTime.now();
        
        System.out.println("Chronology: " + zdt.getChronology());
        System.out.println("Zone: " + zdt.getZone());
        System.out.println("Year: " + zdt.getYear());
        System.out.println("Month: " + zdt.getMonth());
        System.out.println("Day: " + zdt.getDayOfMonth());
        System.out.println("Hour: " + zdt.getHour());
        System.out.println("Minute: " + zdt.getMinute());
        
        // Local date-time without timezone
        System.out.println("Local date-time: " + zdt.toLocalDateTime());
    }
}

此示例展示了如何访问 ChronoZonedDateTime 的各种组件。getChronology 方法返回正在使用的日历系统。所有时态字段都通过标准 getter 方法访问。

时区转换

ChronoZonedDateTime 支持在时区之间转换,同时保留瞬间或本地时间。这些操作对于需要以不同地区显示时间的全球应用程序至关重要。

Main.java
package com.zetcode;

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.chrono.ChronoZonedDateTime;

public class Main {

    public static void main(String[] args) {
        
        ChronoZonedDateTime<?> nyTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("New York time: " + nyTime);
        
        // Convert to Tokyo time (same instant)
        ChronoZonedDateTime<?> tokyoTime = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        System.out.println("Tokyo time (same instant): " + tokyoTime);
        
        // Convert to London time (same local time)
        ChronoZonedDateTime<?> londonTime = nyTime.withZoneSameLocal(ZoneId.of("Europe/London"));
        System.out.println("London time (same local time): " + londonTime);
    }
}

此示例演示了 ChronoZonedDateTime 的时区转换。withZoneSameInstant 更改时区,同时保持相同的瞬间。withZoneSameLocal 保留本地时间,但更改时区,从而产生不同的瞬间。

比较 ChronoZonedDateTime

ChronoZonedDateTime 实例可以按时间顺序进行比较。比较考虑了时间和历法。不同的日历系统可以通过其等效的瞬间进行比较。

Main.java
package com.zetcode;

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.chrono.ChronoZonedDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        ChronoZonedDateTime<?> now = ZonedDateTime.now();
        ChronoZonedDateTime<?> future = now.plus(1, ChronoUnit.HOURS);
        ChronoZonedDateTime<?> past = now.minus(30, ChronoUnit.MINUTES);
        
        System.out.println("Now is before future: " + now.isBefore(future));
        System.out.println("Now is after past: " + now.isAfter(past));
        System.out.println("Comparison result: " + now.compareTo(future));
        
        // Equality considers both chronology and instant
        ChronoZonedDateTime<?> copy = ZonedDateTime.from(now);
        System.out.println("Now equals copy: " + now.equals(copy));
    }
}

此示例展示了比较 ChronoZonedDateTime 对象的各种方法。比较方法考虑了瞬间和历法。请注意,相等性要求历法和瞬间完全匹配。

转换为 Instant 和纪元秒

ChronoZonedDateTime 可以转换为 Instant 和纪元秒,以便与其他时间表示进行互操作。当使用需要机器时间表示的 API 时,这些转换非常有用。

Main.java
package com.zetcode;

import java.time.ZonedDateTime;
import java.time.chrono.ChronoZonedDateTime;

public class Main {

    public static void main(String[] args) {
        
        ChronoZonedDateTime<?> zdt = ZonedDateTime.now();
        
        // Convert to Instant
        System.out.println("As Instant: " + zdt.toInstant());
        
        // Convert to epoch seconds
        System.out.println("Epoch seconds: " + zdt.toEpochSecond());
        
        // Convert from Instant back to ChronoZonedDateTime
        ChronoZonedDateTime<?> fromInstant = 
            ZonedDateTime.ofInstant(zdt.toInstant(), zdt.getZone());
        System.out.println("From Instant: " + fromInstant);
    }
}

此示例演示了 ChronoZonedDateTime 和 Instant 之间的转换。toInstant 方法转换为绝对时间点。toEpochSecond 提供了自 1970-01-01T00:00:00Z 以来秒的计数。

使用不同的历法

ChronoZonedDateTime 通过历法机制支持非 ISO 日历系统。这允许在不同的文化日历系统中处理日期时间,同时保持时区感知能力。

Main.java
package com.zetcode;

import java.time.ZoneId;
import java.time.chrono.HijrahChronology;
import java.time.chrono.JapaneseChronology;
import java.time.chrono.ChronoZonedDateTime;
import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        
        // Japanese calendar
        ChronoZonedDateTime<?> japaneseDate = JapaneseChronology.INSTANCE
            .zonedDateTime(LocalDateTime.now(), ZoneId.systemDefault());
        System.out.println("Japanese date-time: " + japaneseDate);
        
        // Hijrah (Islamic) calendar
        ChronoZonedDateTime<?> hijrahDate = HijrahChronology.INSTANCE
            .zonedDateTime(LocalDateTime.now(), ZoneId.of("Asia/Riyadh"));
        System.out.println("Hijrah date-time: " + hijrahDate);
        
        // Comparing across chronologies
        System.out.println("Same instant: " + 
            japaneseDate.toInstant().equals(hijrahDate.toInstant()));
    }
}

此示例展示了带有非 ISO 日历系统的 ChronoZonedDateTime。使用日本和伊斯兰历法创建日期时间值。尽管日历系统不同,但它们可以通过它们的瞬间值进行比较。

来源

Java ChronoZonedDateTime 接口文档

在本文中,我们介绍了 Java ChronoZonedDateTime 接口的基本方法和特性。理解这些概念对于跨不同日历系统和时区处理日期时间值至关重要。

作者

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

列出所有Java教程