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

Convert OffsetDateTime to LocalDateTime with correct offset in java 8

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

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

您可以尝试以下代码:

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 for more explaination or browse javadoc wbsite

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

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

像这样

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

OffsetDateTime#withOffsetSameInstant

如果您需要将 OffsetDateTime 的对象转换为具有不同 ZoneOffsetOffsetDateTime 对象,您可以使用 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,顾名思义,会丢弃有用的时区信息。然而,LocalDateTime 在某些情况下很有用,如 this page.

中所述

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

Trail: Date Time.

了解有关现代日期时间 API 的更多信息

我想你要找的是OffsetDateTime.atZoneSameInstant:

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