LocalDateTime to specific timezone
Asked Answered
P

4

12

I have a localdatetime object that is in UTC. I want to convert into IST. How can I do that?

LocalDateTime dateTimeOfAfterFiveDays = LocalDateTime.ofEpochSecond(after5,0,ZoneOffset.UTC);
Persia answered 29/5, 2019 at 13:3 Comment(3)
Maybe use ZonedDateTime?Sepalous
LocalDateTime is the wrong class to track a moment.Billbillabong
Assuming after5 is a count of seconds since the epoch, start from Instant.ofEpochSecond(after5) instead. And depending on where after5 comes from, you may want to produce that as an Instant, ZonedDateTime or other object rather than a naked count.Norby
F
31

Since Java 8 the date/time API is pretty easy to work with.

In your case:

// your local date/time with no timezone information
LocalDateTime localNow = LocalDateTime.now();
// setting UTC as the timezone
ZonedDateTime zonedUTC = localNow.atZone(ZoneId.of("UTC"));
// converting to IST
ZonedDateTime zonedIST = zonedUTC.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));

You'll see a difference in the time (and possibly the date) between zonedUTC and zonedIST, reflecting the time zone offset between the two.

Note the usage of withZoneSameInstant here, e.g. as opposed to withZoneSameLocal.

Fictional answered 29/5, 2019 at 13:14 Comment(2)
Wrong class. LocalDateTime cannot represent a moment as it lacks any concept of time zone or offset-from-UTC. I cannot think of a use-case where LocalDateTime.now is ever the right thing.Billbillabong
LocalDateTime here because OP used it. It's not hard to agree LocalDateTime has no tz information, that's pretty much in the name. I'm initializing LocalDateTime.now() because it represents a "now" date/time on this system, with no specific tz attached. The next step is to decide that "here the tz is UTC" and decorating the original object with it. The third step is obtaining a new date time with the tz offset betwen UTC and IST. While LocalDateTime.now usage is indeed unrealistic in real life, this is obviously just an example focusing on the difference between local and zoned...Fictional
B
14

tl;dr

Use Instant, not LocalDateTime for tracking a moment.

Instant                                         // Represents a moment in UTC with a resolution of nanoseconds.
.ofEpochSecond(
    myCountOfWholeSecondsSinceStartOf1970UTC    // Internally, time is tracked as a count of seconds since 1970-01-01T00:00Z plus a fractional second as nanoseconds.
)                                               // Returns a moment in UTC.
.atZone(                                        // Adjust from UTC to another time zone. Same moment, different wall-clock time.
    ZoneId.of( "Asia/Kolkata" )                 // Specify time zone name in `Continent/Region` format, never 2-4 letter pseudo-zone.
)                                               // Returns a `ZonedDateTime` object.
.toString()                                     // Generate a string representing the value of this `ZonedDateTime` in standard ISO 8601 format extended to append the name of the time zone in square brackets.

Wrong class

LocalDateTime dateTimeOfAfterFiveDays = LocalDateTime.ofEpochSecond(after5,0,ZoneOffset.UTC);

LocalDateTime is the wrong class to use here. This class cannot represent a moment. It lacks any concept of time zone or offset-from-UTC. A LocalDateTime holds just a date and a time-of-day, say noon on the 23rd of January this year. But we have no idea if what was intended was noon in Tokyo, noon in Kolkata, noon in Paris, or noon in Montréal — all of these are hours apart, very different moments.

Instant

To represent a moment in UTC, use Instant.

Apparently you have a count of whole seconds since the epoch reference of first moment of 1970 in UTC.

Instant instant = Instant.ofEpochSecond( count ) ;

ZoneId & ZonedDateTime

To see this value through the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime.

Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Billbillabong answered 29/5, 2019 at 17:57 Comment(0)
D
0

In Java 8, you can use ZonedDateTime to convert LocalDateTime with respect to a specific ZoneId. Considering your example, the conversion could be implemented as follows:

ZoneId istZoneId = ZoneId.of("Asia/Kolkata");
LocalDateTime dateTimeOfAfterFiveDays = LocalDateTime.ofEpochSecond(after5,0,ZoneOffset.UTC);
ZonedDateTime zonedDateTimeOfAfterFiveDays = dateTimeOfAfterFiveDays.atZone(istZoneId);

Hope it helps!

Dawes answered 29/5, 2019 at 13:22 Comment(3)
Note that atZone will not alter the date/time. It will only set a timezone on a non-zoned (local) date/time. So if it's 15:30 in the local date/time that needs to be interpreted as UTC within context, atZone on that object will only decorate 15:30 with the desired timezone, i.e. the resulting ZonedDateTime will still be 15:30, only in IST.Fictional
Doesn't LocalDateTime.ofEpochSecond(after5,0,ZoneOffset.UTC) take care of interpreting the local date/time as UTC?Dawes
@LorenzoAddazi You are throwing away the zone/offset information by using LocalDateTime. You might get away with it in this situation, but it makes no sense. ZonedDateTime is the class for this work, not LocalDateTime.Billbillabong
L
0

Code sample in online IDE

package org.example;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
  public static void main(String[] args) {
    LocalDateTime ldt = LocalDateTime.now(); // assume this time is UTC
    System.out.println(ldt);
    ZonedDateTime zoned = ldt.atZone(ZoneId.of("UTC"));
    Instant instant=zoned.toInstant();
    ldt=instant.atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime();
    System.out.println(ldt);
  }
}
Ludhiana answered 17/7 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.