Reputation: 320
I need to do a LocalDateTime
conversion of a UTC date to another LocalDateTime
variable considering a specific timezone tz.
During my research I found many solutions, but they all convert the LocalDateTime
to another type, like ZonedDateTime
.
I need something like that, but LocalDateTime
wont work with ZoneId
:
LocalDateTime output = input.getInitDate().of(ZoneId.of(tz))
Considering a -3 timezone:
input: 2019-12-03T18:24:07
output: 2019-12-03T15:24:07
Upvotes: 4
Views: 2204
Reputation: 338181
Your Question makes no sense.
You need to understand that LocalDateTime
holds nothing but a date and a time-of-day. The class purposely lacks any concept of time zone or offset-from-UTC. So LocalDateTime
does not represent a moment. The name can be misleading, as a LocalDateTime
is not about any particular locality.
If you want to track a moment in UTC, use Instant
.
Instant instant = Instant.now() ; // Capture the current moment in UTC. Always in UTC, by definition.
If you want to track a moment as seen in the wall-clock time used by the people of a particular region (a time zone), use ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Montevideo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
LocalDateTime conversion of a UTC date
Do you mean you have particular date and time in mind as seen at the prime meridian? Or as seen in Iceland which uses UTC as their time zone?
LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 15 , 0 ) ; // 3 PM.
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
This ldt
object means "3 PM on the 23rd of January this year" somewhere, or anywhere. But that LocalDateTime
object does not 3 PM in one particular place. We have no idea if the intention here is 3 PM in Tokyo Japan or 3 PM in Toulouse France or 3 PM in Toledo Ohio US. Those would be three different moments, several hours apart. A LocalDateTime
represents none of them, or all of them, whichever way you want to see it, but not any one of them.
To determine a moment from a date and a time-of-day, you need the context of a time zone or offset-from-UTC. In other words the third piece of information, in addition to the date and the time-of-day, we need is "as seen in Paris France" or "as seen in Palmer Station in Antarctica". With such a context, we get either ZonedDateTime
or OffsetDateTime
, respectively.
ZoneId z = ZoneId.of( "Antarctica/Palmer" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ldt , z ) ; // Giving context of time zone to the date-with-time `LocalDateTime` object. Determines a moment.
To see that same moment in UTC (an offset of zero hours-minutes-seconds), extract an Instant
.
Instant instant = zdt.toInstant() ; // Adjust from time zone to UTC.
Considering a -3 timezone:
No, -3
is not a time zone, it is an offset.
The -3
is short for -03:00
. Practically speaking, I suggest you avoid abbreviating the offset as some libraries expect a full hours-with-minutes including the colon character, and including the leading zero on single-digit hours or minutes.
The -3
or -03:00
means simply "three hours behind UTC".
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. A time zone has a name in the form of Continent/Region
such as Africa/Tunis
or Europe/Paris
.
See the list of time zones on Wikipedia. Sort by offset column. Notice how around three dozen time zones may today be sharing the offset of -03:00
such as America/Montevideo
, Atlantic/Stanley
, and Antarctica/Palmer
.
Always prefer a time zone to a mere offset. When doing date-time math and adding/subracting spans of time, the results may vary by time zone. Time zones may be using different offsets other than -03:00
on other dates in the past and in the future.
Upvotes: 6
Reputation: 117569
You need to convert it first to ZonedDateTime
, change the timezone, and then extract LocalDateTime
from that:
ZoneId from = ...;
ZoneId to = ...;
LocalDateTime input = ...;
LocalDateTime output = input.atZone(from).withZoneSameInstant(to).toLocalDateTime();
Upvotes: 7
Reputation: 4365
Try this solution:
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
ZonedDateTime ldtZoned = ldt.atZone(ZoneId.systemDefault());
ZonedDateTime utcZoned = ldtZoned.withZoneSameInstant(ZoneId.of("UTC-3"));
System.out.println(utcZoned.toLocalDateTime());
It gives the output:
2020-02-03T20:55:33.313882
2020-02-03T17:55:33.313882
Upvotes: 3