Convert UTC datetime to local datetime using java.time

1.4k Views Asked by At

I have a UTC date-time like this (a String): 2022-11-22T17:15:00

And a ZoneID like this: "America/Tijuana"

Using java.time API, I want to get the actual datetime for that zone, which is: 2022-11-22T09:15:00 (the time is 09:15 instead of 17:15)

  • ZonedDateTime.toLocalDateTime() returns: 2022-11-22T17:15
  • ZonedDateTime.toString() returns: 2022-11-22T17:15-08:00[America/Tijuana]

None of the above gives me what I'm looking for.

This is my code:

    ZoneId zonaID = ZoneId.of('America/Tijuana');
    CharSequence dateUTC = "2022-11-22T17:15:00";
    LocalDateTime dateTimeL = LocalDateTime.parse(dateUTC);
    ZonedDateTime myZDT = ZonedDateTime.now();
    ZonedDateTime myZDTFinal = myZDT.of(dateTimeL, zonaID);
    System.out.println("using toLocalDateTime: " + myZDTFinal.toLocalDateTime());
    System.out.println("using toString: " + myZDTFinal.toString());

I know that this might be a duplicated question but there's so many questions about date-times and I just haven't been able to figure out this.

Any help will be really appreciated.

2

There are 2 best solutions below

1
Arvind Kumar Avinash On BEST ANSWER

There can be many ways to achieve the result. A simple approach would be

  1. Parse the given string into LocalDateTime.
  2. Convert it into an OffsetDateTime at UTC using LocalDateTime#atOffset.
  3. Use OffsetDateTime#atZoneSameInstant to convert the resulting OffsetDateTime into a ZonedDateTime at ZoneId.of("America/Tijuana").
  4. Get LocalDateTime out of the resulting ZonedDateTime by using ZonedDateTime#toLocalDateTime.
  5. If required, format this LocalDateTime into the desired string.
LocalDateTime
    .parse("2022-11-22T17:15:00") // Parse the given date-time string into LocalDateTime
    .atOffset(ZoneOffset.UTC) // Convert it into a ZonedDateTime at UTC
    .atZoneSameInstant(ZoneId.of("America/Tijuana")) // Convert the result into a ZonedDateTime at another time-zome
    .toLocalDateTime() // Get the LocalDateTime out of the ZonedDateTime
    .format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss", Locale.ENGLISH))); // If required

Demo:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDateTime ldtInTijuana = LocalDateTime.parse("2022-11-22T17:15:00")
                .atOffset(ZoneOffset.UTC)
                .atZoneSameInstant(ZoneId.of("America/Tijuana"))
                .toLocalDateTime();
        System.out.println(ldtInTijuana);

        // Custom format
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
        String formatted = ldtInTijuana.format(formatter);
        System.out.println(formatted);
    }
}

Output:

2022-11-22T09:15
2022-11-22T09:15:00

Note that LocalDateTime#toString removes second and fraction-of-second values if they are zero. Suppose you want to keep them (as you have posted in your question), you can use a DateTimeFormatter as shown above.

An alternate approach:

Alternatively, you can append Z at the end of your ISO 8601 formatted date-time string to enable Instant to parse it and then convert the Instant into a ZonedDateTime corresponding to the ZoneId.of("America/Tijuana") by using Instant#atZone. The symbol, Z refers to UTC in a date-time string.

The rest of the steps will remain the same.

Demo:

public class Main {
    public static void main(String[] args) {
        String text = "2022-11-22T17:15:00";
        text = text + "Z"; // Z refers to UTC
        Instant instant = Instant.parse(text);
        LocalDateTime ldt = instant.atZone(ZoneId.of("America/Tijuana")).toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2022-11-22T09:15

Learn more about the modern Date-Time API from Trail: Date Time.

1
Youcef LAIDANI On

You have to convert your date to UTC, then convert the convert this zone to your expected zone using withZoneSameInstant like this:

ZonedDateTime toUTCZone  = ZonedDateTime.of(dateTimeL, ZoneOffset.UTC);
ZonedDateTime myZDTFinal = toUTCZone.withZoneSameInstant(zonaID);

Output

2022-11-22T09:15-08:00[America/Tijuana]