Vinícius Britto
Vinícius Britto

Reputation: 320

Convert LocalDateTime to LocalDateTime with specific Zone in Java

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

Answers (3)

Basil Bourque
Basil Bourque

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.

Time zone versus offset-from-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.


Table of all date-time types in Java, both modern and legacy

Upvotes: 6

Eng.Fouad
Eng.Fouad

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

Iskuskov Alexander
Iskuskov Alexander

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

Related Questions