Convert OffsetDateTime to LocalDateTime with correct offset in java 8

Viewed 8837

When I try to convert OffsetDateTime to LocalDateTime from java.time, I expect the resulting LocalDateTime to be updated with the local time zone. So, If I have an OffsetDateTime of 2011-12-03T10:00:00Z, and my local timezone is UTC+2, I expect the LocalDateTime to be 2011-12-03T12:00:00, but I get instead 2011-12-03T10:00:00. I'm converting it with the method toLocalDateTime() that OffsetDateTime has. It seems that it only truncates the date, removing the offset part, without adjusting the time.

So I'm trying to figure out a way to get a LocalDateTime that represents the local date time taking into account the zone offset. Following the example, I would like to get 2011-12-03T12:00:00

5 Answers

LocalDateTime would give you the time of a wall clock of your OffsetDateTime. That's 10:00

You need to first convert to a ZonedDatedTime in your time zone

Like this

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);

I think what you are looking for is OffsetDateTime.atZoneSameInstant:

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

OffsetDateTime#withOffsetSameInstant

If you need to convert an object of OffsetDateTime to an OffsetDateTime object with a different ZoneOffset, you can do so by using OffsetDateTime#withOffsetSameInstant.

Demo:

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);
    }
}

Output:

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

ONLINE DEMO

I suggest you keep using OffsetDateTime because LocalDateTime, as the name suggests, throws away the useful timezone information. Nevertheless, LocalDateTime is useful in some scenarios as mentioned on this page.

If you are dealing with JDBC, check this answer and this answer.

Learn more about the modern Date-Time API from Trail: Date Time.

I think the most concise solution is

LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC)

Here is some code you can try :

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);

Output

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

You can take a look on this website for more explaination or browse javadoc wbsite.

Related