Vinod
Vinod

Reputation: 57

How to convert ZonedDateTime to LocalDateTime?

I want to convert local date and time to UTC and then back to local date and time, I could not find solutions on internet. I used below code:

// get local date and time
LocalDateTime localDateTime = LocalDateTime.now();
// print local date time
System.out.println(localDateTime);
// get system time zone / zone id
ZoneId zoneId = ZoneId.systemDefault();
// get UTC time with zone offset
ZonedDateTime zonedDateTime = LocalDateTime.now(ZoneOffset.UTC).atZone(zoneId);
System.out.println(zonedDateTime);
// now I want to convert the UTC with timezone back to local time, 
// but below code is not working  
System.out.println(zonedDateTime.toLocalDateTime());

result expected

local date and time = 2023-08-01T17:15:10.832796200  
zoned date and time = 2023-08-01T11:45:10.832796200+05:30[Asia/Calcutta]  
local date and time after conversion = 2023-08-01T17:15:10.832796200

Upvotes: 0

Views: 1311

Answers (2)

deHaar
deHaar

Reputation: 18558

Just in addition to the answer by @rzwitzerloot…

Use a definite moment in time as base for coversion and zone hopping.

java.time has such a definite moment in time: An Instant

Here's some example:

public static void main(String[] args) {
    ZoneId zoneId = ZoneId.of("Asia/Calcutta");
    // get a moment in time (Unix epoch) and use it as base
    Instant now = Instant.now();
    // get the local date and time in your zone based on the instant
    LocalDateTime local = LocalDateTime.ofInstant(now, zoneId);
    System.out.println(local);
    // get the zoned date and time in UTC based on the instant
    ZonedDateTime utc = ZonedDateTime.ofInstant(now, ZoneOffset.UTC);
    System.out.println(utc);
    // get the zoned date and time in your zone based on the instant 
    ZonedDateTime localZone = ZonedDateTime.ofInstant(now, zoneId);
    System.out.println(localZone);
    // extract the local date and time from it
    LocalDateTime backToLocal = localZone.toLocalDateTime();
    // then check for equality
    if (local.equals(backToLocal)) {
        System.out.println(local + " == " + backToLocal);
    } else {
        System.err.println(local + " != " + backToLocal);
    }
}

Output (right now):

2023-08-01T20:14:39.776239
2023-08-01T14:44:39.776239Z
2023-08-01T20:14:39.776239+05:30[Asia/Calcutta]
2023-08-01T20:14:39.776239 == 2023-08-01T20:14:39.776239

I used a fix ZoneId in order to have yours in the example.

Upvotes: 0

rzwitserloot
rzwitserloot

Reputation: 102785

ZonedDateTime zonedDateTime = LocalDateTime.now(ZoneOffset.UTC).atZone(zoneId);

This is suspect code. This code says:

What time is it right now in the UTC zone. So, here in Amsterdam it's 15:46, but if I were to run that (we're in summer time right now, amsterdam has a +2 offset), LocalDateTime.now(ZoneOffset.UTC) gives me a local DT object with local time 13:46. It doesn't have a timezone, because.. it's local date time.

You then 'place' that time (of 13:46) in a zone. Let's say zoneId is Europe/Amsterdam, this code gets me a time that happened 2 hours ago. It doesn't make any sense, you would never want to write this code.

What you presumably want is:

LocalDateTime nowAtUtc = LocalDateTime.now(ZoneOffset.UTC);
ZonedDateTime zoned = nowAtUtc.atZone(ZoneOffset.UTC);
ZonedDateTime inAmsterdam = zoned.atZoneSameInstant(ZoneId.of("Europe/Amsterdam"));
System.out.println(inAmsterdam.toLocalDateTime());

the above code prints the current time as per my clock here in The Netherlands.

Of course, that exact snippet is pointless - why convert from A to B and right back again? Ordinarily you'd just go LocalDateTime.now() if you want an LDT, or if you want a ZDT, simply ZonedDateTime.now(zoneYouAreInterestedIn);. However, I assume you asked the question because you do a bunch of stuff in between that you elided from the question.

Upvotes: 2

Related Questions