ZetCode

Java OffsetDateTime 类

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

java.time.OffsetDateTime 类表示带有时区偏移量的日期时间。 它存储所有日期和时间字段,精确到纳秒,并带有与 UTC 的偏移量。

OffsetDateTime 是不可变的且线程安全的。 它用于在数据库中存储时间戳或表示固定偏移时间。 该类将 LocalDateTime 与 ZoneOffset 结合起来,提供完整的时间戳。

OffsetDateTime 类概述

OffsetDateTime 提供了创建、解析和操作带有时区偏移量的日期时间值的方法。 关键操作包括调整偏移量、比较值以及转换为其他时间类型。

public final class OffsetDateTime implements Temporal, TemporalAdjuster, 
    Comparable<OffsetDateTime>, Serializable {
    public static OffsetDateTime now();
    public static OffsetDateTime of(LocalDateTime dateTime, ZoneOffset offset);
    public static OffsetDateTime parse(CharSequence text);
    public LocalDateTime toLocalDateTime();
    public ZoneOffset getOffset();
    public OffsetDateTime withOffsetSameLocal(ZoneOffset offset);
    public boolean isAfter(OffsetDateTime other);
    public boolean isBefore(OffsetDateTime other);
    public OffsetDateTime plus(long amountToAdd, TemporalUnit unit);
    public OffsetDateTime minus(long amountToSubtract, TemporalUnit unit);
}

上面的代码显示了 OffsetDateTime 提供的关键方法。 这些方法允许创建、比较和操作带有时区偏移量的日期时间值。 该类提供纳秒级的精度,同时保留偏移量信息。

创建 OffsetDateTime 对象

OffsetDateTime 对象可以通过多种方式创建。 最常用的方法是使用 now 获取当前时间,以及使用工厂方法创建特定时间点。 也支持从字符串解析。

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) {
        
        // Current offset date-time
        OffsetDateTime now = OffsetDateTime.now();
        System.out.println("Current offset date-time: " + now);
        
        // From LocalDateTime and ZoneOffset
        LocalDateTime ldt = LocalDateTime.of(2025, 6, 15, 14, 30);
        ZoneOffset offset = ZoneOffset.ofHours(2);
        OffsetDateTime odt = OffsetDateTime.of(ldt, offset);
        System.out.println("From LocalDateTime: " + odt);
        
        // From string
        OffsetDateTime parsed = OffsetDateTime.parse("2025-01-01T12:00:00+01:00");
        System.out.println("Parsed from string: " + parsed);
        
        // With specific offset
        OffsetDateTime withOffset = now.withOffsetSameLocal(ZoneOffset.of("-05:00"));
        System.out.println("With -05:00 offset: " + withOffset);
    }
}

此示例演示了创建 OffsetDateTime 对象的不同方法。 输出显示了带有偏移量的 ISO-8601 格式的日期时间值。 now 方法使用系统默认偏移量。

访问日期时间组件

OffsetDateTime 可以分解为其日期、时间以及偏移量组件。 可以单独访问这些值以进行处理或显示。

Main.java
package com.zetcode; 

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

public class Main {

    public static void main(String[] args) {

        OffsetDateTime odt = OffsetDateTime.now();
        
        // Get date components
        System.out.println("Year: " + odt.getYear());
        System.out.println("Month: " + odt.getMonth());
        System.out.println("Day: " + odt.getDayOfMonth());
        
        // Get time components
        System.out.println("Hour: " + odt.getHour());
        System.out.println("Minute: " + odt.getMinute());
        System.out.println("Second: " + odt.getSecond());
        System.out.println("Nano: " + odt.getNano());
        
        // Get offset
        ZoneOffset offset = odt.getOffset();
        System.out.println("Offset: " + offset);
        
        // Get LocalDateTime part
        System.out.println("Local date-time: " + odt.toLocalDateTime());
    }
}

此示例展示了如何从 OffsetDateTime 中提取组件。 该类提供了分别访问所有日期和时间字段的方法。 偏移量表示与 UTC 的时间差。

比较 OffsetDateTime 值

可以比较 OffsetDateTime 值以确定时间顺序。 该类提供了 isBeforeisAftercompareTo 方法。 比较考虑了瞬间和本地日期时间。

Main.java
package com.zetcode; 

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        OffsetDateTime now = OffsetDateTime.now();
        OffsetDateTime later = now.plus(1, ChronoUnit.HOURS);
        OffsetDateTime earlier = now.minus(30, ChronoUnit.MINUTES);
        
        System.out.println("Now is before later: " + now.isBefore(later));
        System.out.println("Now is after earlier: " + now.isAfter(earlier));
        System.out.println("Comparison result: " + now.compareTo(later));
        
        // Different offsets same instant
        OffsetDateTime nyTime = now.withOffsetSameInstant(ZoneOffset.of("-05:00"));
        System.out.println("Same instant different offset: " + now.isEqual(nyTime));
    }
}

此示例演示了比较 OffsetDateTime 对象的各种方法。 比较方法考虑了瞬间和本地日期时间。 请注意,isEqual 比较了瞬间,而忽略了偏移量。

调整偏移量

OffsetDateTime 提供了在保持本地日期时间或瞬间不变的情况下调整偏移量的方法。 这些操作在不同偏移量表示之间进行转换时非常有用。

Main.java
package com.zetcode; 

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

public class Main {

    public static void main(String[] args) {

        OffsetDateTime now = OffsetDateTime.now();
        System.out.println("Original: " + now);
        
        // Keep local time, change offset
        OffsetDateTime sameLocal = now.withOffsetSameLocal(ZoneOffset.of("+05:30"));
        System.out.println("Same local, new offset: " + sameLocal);
        
        // Keep instant, change offset (adjusts local time)
        OffsetDateTime sameInstant = now.withOffsetSameInstant(ZoneOffset.of("-08:00"));
        System.out.println("Same instant, new offset: " + sameInstant);
        
        // Convert to UTC
        OffsetDateTime utc = now.withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println("UTC equivalent: " + utc);
    }
}

此示例展示了如何在保持本地日期时间或瞬间不变的情况下调整偏移量。 withOffsetSameLocal 在不改变本地时间的情况下更改偏移量。 withOffsetSameInstant 调整本地时间以保持相同的瞬间。

日期时间运算

OffsetDateTime 通过 plusminus 方法支持时间运算。 这些操作对于计算未来或过去的时间点,同时保持偏移量非常有用。

Main.java
package com.zetcode; 

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.Duration;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        OffsetDateTime now = OffsetDateTime.now();
        
        // Add days
        OffsetDateTime in5Days = now.plusDays(5);
        System.out.println("In 5 days: " + in5Days);
        
        // Subtract hours
        OffsetDateTime twoHoursAgo = now.minusHours(2);
        System.out.println("Two hours ago: " + twoHoursAgo);
        
        // Add using Duration
        OffsetDateTime in30Mins = now.plus(Duration.ofMinutes(30));
        System.out.println("In 30 minutes: " + in30Mins);
        
        // Complex operation
        OffsetDateTime complex = now.plus(1, ChronoUnit.WEEKS)
                                  .minus(3, ChronoUnit.DAYS)
                                  .plusHours(6);
        System.out.println("Complex operation result: " + complex);
    }
}

此示例显示了使用 OffsetDateTime 执行时间运算的各种方法。 运算可以使用特定单位或 Duration 对象。 所有计算都保留了原始偏移量,除非显式更改。

在时间类型之间转换

OffsetDateTime 可以转换为其他时间类型,例如 ZonedDateTime 和 Instant,也可以从这些类型转换。 当处理不同的时间表示时,这些转换是必不可少的。

Main.java
package com.zetcode; 

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.Instant;

public class Main {

    public static void main(String[] args) {

        OffsetDateTime odt = OffsetDateTime.now();
        
        // Convert to Instant
        Instant instant = odt.toInstant();
        System.out.println("As Instant: " + instant);
        
        // Convert to ZonedDateTime
        ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("Europe/Paris"));
        System.out.println("In Paris: " + zdt);
        
        // Convert from Instant
        OffsetDateTime fromInstant = Instant.now().atOffset(ZoneOffset.ofHours(3));
        System.out.println("From Instant: " + fromInstant);
        
        // Convert from ZonedDateTime
        OffsetDateTime fromZdt = ZonedDateTime.now().toOffsetDateTime();
        System.out.println("From ZonedDateTime: " + fromZdt);
    }
}

此示例演示了 OffsetDateTime 和其他时间类型之间的转换。 请注意,转换为 ZonedDateTime 需要时区,而 OffsetDateTime 仅存储偏移量。 所有转换都保留了所表示的确切时刻。

来源

Java OffsetDateTime 类文档

在本文中,我们介绍了 Java OffsetDateTime 类的基本方法和特性。 理解这些概念对于在现代 Java 应用程序中准确地处理带偏移量的时间至关重要。

作者

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

列出所有Java教程