在java 8中使用正确的偏移量将OffsetDateTime转换为LocalDateTime

问题描述

当我尝试将 OffsetDateTime 从 java.time 转换为 LocalDateTime 时,我希望生成LocalDateTime 使用本地时区进行更新。因此,如果我的 OffsetDateTime2011-12-03T10:00:00Z,并且我的本地时区是 UTC+2,我希望 LocalDateTime 为 2011-12-03T12:00:00,但我得到的是 2011-12-03T10:00:00。我正在使用 toLocalDateTime() 具有的方法 OffsetDateTime 转换它。好像只是截断了日期,去掉了偏移部分,没有调整时间。

所以我试图找出一种方法来获得一个 LocalDateTime 来代表本地日期时间,同时考虑到区域偏移。按照这个例子,我想得到 2011-12-03T12:00:00

解决方法

LocalDateTime 将为您提供 OffsetDateTime 的挂钟时间。那是 10:00

您需要先转换为您所在时区的 ZonedDatedTime

像这样

OffsetDateTime off = OffsetDateTime.of(2011,12,3,10,00,ZoneOffset.UTC);
ZonedDateTime zoned = off.atZoneSameInstant(ZoneId.of("Europe/Athens"));
LocalDateTime athensWallTime = zoned.toLocalDateTime();
System.out.println(athensWallTime);
,

OffsetDateTime#withOffsetSameInstant

如果您需要将 OffsetDateTime 的对象转换为具有不同 OffsetDateTimeZoneOffset 对象,您可以使用 OffsetDateTime#withOffsetSameInstant 来实现。

演示:

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

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2011-12-03T10:00:00Z");

        OffsetDateTime odtWithOffsetTwoHours = odt.withOffsetSameInstant(ZoneOffset.of("+02:00"));
        System.out.println(odtWithOffsetTwoHours);

        LocalDateTime ldt = odtWithOffsetTwoHours.toLocalDateTime();
        System.out.println(ldt);
    }
}

输出:

2011-12-03T12:00+02:00
2011-12-03T12:00

ONLINE DEMO

我建议您继续使用 OffsetDateTime,因为顾名思义,LocalDateTime 会丢弃有用的时区信息。尽管如此,LocalDateTimethis page 中提到的某些情况下很有用。

如果您正在处理 JDBC,请检查 this answerthis answer

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。

,

我认为您正在寻找的是OffsetDateTime.atZoneSameInstant

OffsetDateTime.parse("2011-12-03T10:00:00Z")
    .atZoneSameInstant(ZoneId.systemDefault())
    .toLocalDateTime()
,

这是一些您可以尝试的代码:

public static void main(String[] args) {
        OffsetDateTime offsetDT1 = OffsetDateTime.now();
        System.out.println("OffsetDateTime1: " + offsetDT1);
 
        OffsetDateTime offsetDT2 = OffsetDateTime.now(Clock.systemUTC());
        System.out.println("OffsetDateTime2: " + offsetDT2);
        
        OffsetDateTime offsetDT3 = OffsetDateTime.now(ZoneId.of("Asia/Jakarta"));
        System.out.println("OffsetDateTime3: " + offsetDT3);
        
        OffsetDateTime offsetDT4 = OffsetDateTime.of(1980,4,9,20,15,45,345875000,ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime4: " + offsetDT4);
        
        OffsetDateTime offsetDT5 = OffsetDateTime.of(LocalDate.now(),LocalTime.of(15,50,25),ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime5: " + offsetDT5);
        
        OffsetDateTime offsetDT6 = OffsetDateTime.of(LocalDateTime.now(),ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime6: " + offsetDT6);
        
        OffsetDateTime offsetDT7 = OffsetDateTime.ofInstant(Instant.now(),ZoneId.systemDefault());
        System.out.println("OffsetDateTime7: " + offsetDT7);
        
        OffsetDateTime offsetDT8 = OffsetDateTime.parse("2019-08-31T15:20:30+08:00");
        System.out.println("OffsetDateTime8: " + offsetDT8);
        
        OffsetDateTime offsetDT9 = OffsetDateTime.parse("1980-04-09T08:20:45+07:00",DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        System.out.println("OffsetDateTime9: " + offsetDT9);

输出

OffsetDateTime1: 2019-08-31T23:49:05.629+08:00
OffsetDateTime2: 2019-08-31T15:49:05.630Z
OffsetDateTime3: 2019-08-31T22:49:05.630+07:00
OffsetDateTime4: 1980-04-09T20:15:45.345875+07:00
OffsetDateTime5: 2019-08-31T15:50:25+07:00   
OffsetDateTime6: 2019-08-31T23:49:05.631+07:00
OffsetDateTime7: 2019-08-31T23:49:05.631+08:00
OffsetDateTime8: 2019-08-31T15:20:30+08:00
OffsetDateTime9: 1980-04-09T08:20:45+07:00

您可以查看此 website 以获取更多说明或浏览 javadoc wbsite