3

Converting this string "2021-04-14T20:51:21.527Z" into a UTC value.

The following works, but is very verbose...

protected final LocalDateTime dateTimeOfLoss = LocalDateTime.ofInstant(Instant.parse("2021-04-14T20:51:21.527Z"), ZoneId.of(ZoneOffset.UTC.getId()));
protected final ZonedDateTime zdt = dateTimeOfLoss.atZone(ZoneId.of(ZoneOffset.UTC.getId()));

I am going for readability, this is for a test.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Leon Gaban
  • 36,509
  • 115
  • 332
  • 529

3 Answers3

7

Assuming you need both of these fields, flip them round to construct the ZonedDateTime first. You can then get the LocalDateTime without having to specify the zone again:

protected final ZonedDateTime zdt = Instant.parse("2021-04-14T20:51:21.527Z").atZone(ZoneOffset.UTC);
protected final LocalDateTime dateTimeOfLoss = zdt.toLocalDateTime();

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
4

Just parse to Instant.

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

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2021-04-14T20:51:21.527Z");
        System.out.println(instant);

        // If you want to convert it to ZonedDateTime
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Etc/UTC"));
        System.out.println(zdt);

        // If you want to convert it to OffsetDateTime
        OffsetDateTime odt = instant.atOffset(ZoneOffset.UTC);
        System.out.println(odt);

        // If you want to convert it to LocalDate
        LocalDateTime ldt = zdt.toLocalDateTime(); // Alternatively, odt.toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2021-04-14T20:51:21.527Z
2021-04-14T20:51:21.527Z[Etc/UTC]
2021-04-14T20:51:21.527Z
2021-04-14T20:51:21.527

Instant represents an instantaneous point on the timeline and the value you get on parsing is already in UTC. The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Learn more about java.time, the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

Go for OffsetDateTime

You are not using the right types. Your string value, 2021-04-14T20:51:21.527Z, is appropriate for either an Instant or an OffsetDateTime. Your use of LocalDateTime in particular seems to indicate to me that you need date and/or time of day, not just the moment in time. If so, go for an OffsetDateTime.

protected final OffsetDateTime dateTimeOfLoss
        = OffsetDateTime.parse("2021-04-14T20:51:21.527Z");

Then you should not have any good use for LocalDateTime nor ZonedDateTime. If you still need one of those, maybe for an API that you cannot change, write a conversion method:

protected LocalDateTime getDateTimeOfLossLdt() {
    return dateTimeOfLoss.toLocalDateTime();
}

protected ZonedDateTime getZdt() {
    return dateTimeOfLoss.atZoneSameInstant(dateTimeOfLoss.getOffset());
}

Why?

LocalDateTime is not right: There are few good uses for LocalDateTime at all. Most often date and time is used for establishing a point in time, and your string does that by including the trailing Z that denotes offset zero from UTC. By converting to LocalDateTime you are discarding that offset and hence losing information about which moment in time you had and getting nothing in return. LocalDateTime gives you nothing that OffsetDateTime does not give you.

ZonedDateTime is not right: As I said, your string contains a UTC offset. It does not contain a time zone. Asia/Krasnoyarsk and America/Grand_Turk are examples of time zones. So while a ZonedDateTime works, it’s really unmotivated. I think of it as more heavy-weight than you need since a time zone includes historic and known future UTC offsets, information that you cannot meaningfully use here.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161