Reputation: 365
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
Upvotes: 16
Views: 36404
Reputation: 10507
The answer marked as correct put me in the right direction to make it a little bit more production oriented. Also, I need this for Kotlin, so considering it is retro-compatible, here it goes.
For me, what worked was using withOffsetSameInstant
. This method requires the offset, and I think the key is to obtain it from the system to provide the user with the visualization in its own time.
The offset can be obtained like this:
val offset = OffsetDateTime.now().offset
And then we proceed to parse the date-time text to OffsetDateTime
:
val dateTime = "2023-01-20T01:00:00+00:00"
val offsetDateTime = OffsetDateTime.parse(dateTime).withOffsetSameInstant(offset)
Then we can obtain the local date-time like this:
val localDateTime = offsetDateTime.toLocalDateTime()
println(localDateTime)
Let's say that my offset is minus 3 (-03:00). Then that should print:
2023-01-19T22:00
This, for me, seems ok because it was day 20th at 1:00 am, so with minus 3, it should be the day 19th.
A small clarification regarding using a formatter. For the format above, you don't need to provide a DateTimeFormatter
because the method parse
with a single argument; assumes it is ISO, and the format above is ISO (DateTimeFormatter.ISO_OFFSET_DATE_TIME
).
This is how you can create a formatter in case you need it:
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX")
Upvotes: 0
Reputation: 106
I think the most concise solution is
LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC)
Upvotes: -1
Reputation: 79055
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
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.
Upvotes: 5
Reputation: 23091
I think what you are looking for is OffsetDateTime.atZoneSameInstant
:
OffsetDateTime.parse("2011-12-03T10:00:00Z")
.atZoneSameInstant(ZoneId.systemDefault())
.toLocalDateTime()
Upvotes: 9
Reputation: 1939
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);
Upvotes: 22
Reputation: 553
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.
Upvotes: -2