How to convert "2020-12-20T00:00:00.000Z" to java.util.Date?
Asked Answered
E

5

7

I tried to use

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDate date = LocalDate.parse(d.toString(), formatter);

but it throws an error.

Is there any way to convert the JSON default timestamp?

Epley answered 29/7, 2020 at 15:21 Comment(6)
What error does it throw, exactly?Sordello
Don't use java.util.Date if you can avoid it. Use Instant instead.Lungwort
I was using it for HibernateEpley
See this answer: https://mcmap.net/q/53802/-converting-iso-8601-compliant-string-to-java-util-date (as your format seems to be ISO compliant)Sordello
That said, if this is comming from JSON, your JSON parser library may also provide a function for this.Sordello
@Epley - If one of the answers resolved your issue, you can help the community by marking that as accepted. An accepted answer helps future visitors use the solution confidently.Jehiel
E
8

You need to use LocalDateTime.

DateTimeFormatter formatter = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDateTime date = LocalDateTime.parse(d.toString(), formatter);
Endotoxin answered 29/7, 2020 at 15:29 Comment(1)
ofPattern requires Android API26Pyroligneous
J
7

You do not need DateTimeFormatter to parse your date-time string

Parse the given date string directly to OffsetDateTime. The modern date-time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the date-time string conforms to the ISO 8601 standards. The Z in your date-time string 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).

OffsetDateTime odt = OffsetDateTime.parse("2020-12-20T00:00:00.000Z");

Convert the OffsetDateTime into Instant

Convert the OffsetDateTime into Instant using OffsetDateTime#toInstant. An Instant represents an instantaneous point on the timeline. It is independent of a timezone and thus, it is always in UTC.

Instant instant = odt.toInstant();

Stop using the legacy date-time API

With the release of Java SE 8 in March 2014, the outdated and error-prone legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat etc.) was supplanted by java.time, the modern date-time API*. It is strongly recommended to stop using the legacy API and switch to this new API. If at all, you need java.util.Date, get it using java.util.Date#from(Instant).

java.util.Date date = Date.from(instant);

Note that the java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat and obtain the formatted string from it e.g.

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(date));

You can convert an Instant to other date-time types

You can convert an Instant to other date-time types easily e.g. if you want to convert it into a ZonedDateTime instance representing the date-time in London, you can do so as

ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));

LocalDateTime is useless in your case

Quoted below is a very good description of the uses of LocalDateTime:

This class can be used to represent a specific event, such as the first race for the Louis Vuitton Cup Finals in the America's Cup Challenger Series, which began at 1:10 p.m. on August 17, 2013. Note that this means 1:10 p.m. in local time.

The best use of your date-time string is as an OffsetDateTime which you have obtained in the first step itself.

Demo:

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

public class Main {
    public static void main(String[] args) {
        // Parse the date-time string into OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse("2020-12-20T00:00:00.000Z");
        System.out.println(odt);

        // Convert OffsetDateTime into Instant
        Instant instant = odt.toInstant();

        // If at all, you need java.util.Date
        Date date = Date.from(instant);
        System.out.println(date);

        // You can convert an `Instant` to other date-time types easily
        // e.g. to ZoneDateTime in a specific timezone
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));
        System.out.println(zdt);

        // e.g. to OffsetDateTime with a specific timezone offset
        OffsetDateTime odt0530 = instant.atOffset(ZoneOffset.of("-05:30"));
        System.out.println(odt0530);

        // e.g. to LocalDateTime via an OffsetDateTime or a ZonedDateTime
        LocalDateTime ldt = odt.toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2020-12-20T00:00Z
Sun Dec 20 00:00:00 GMT 2020
2020-12-20T00:00Z[Europe/London]
2020-12-19T18:30-05:30
2020-12-20T00:00

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.

Jehiel answered 29/7, 2020 at 15:37 Comment(1)
Instant class only available on Android 26 and above. if you are looking for backward compatibility , you need to stick with SimpleDateFormat only.Jungle
H
3

To your question on how to convert LocalDate to java.util.Date, you can use Date.from method as follows. Let me know if that is what you are expecting to achieve.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDate localDate = LocalDate.parse("2020-12-20T00:00:00.000Z", formatter);
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
System.out.println(date);
Herman answered 29/7, 2020 at 15:47 Comment(0)
R
2

This seems to be default format, please try this one.

ZonedDateTime dateTime  = ZonedDateTime.parse("2020-07-28T14:28:52.877Z");

// In case you still need LocalDateTime
LocalDateTime localDateTime  = dateTime.toLocalDateTime();

Relation answered 29/7, 2020 at 15:29 Comment(0)
C
2

The Z is the Zulu time-zone (i.e. the UTC time-zone), not a literal Z.

This whole format is the ISO-8601 instant format.

There is a pre-existing formatter for that: DateTimeFormatter#ISO_INSTANT

Extract from the javadoc:

public static final DateTimeFormatter ISO_INSTANT

The ISO instant formatter that formats or parses an instant in UTC, such as '2011-12-03T10:15:30Z'.

This returns an immutable formatter capable of formatting and parsing the ISO-8601 instant format. When formatting, the second-of-minute is always output. The nano-of-second outputs zero, three, six or nine digits digits as necessary. When parsing, time to at least the seconds field is required. Fractional seconds from zero to nine are parsed. The localized decimal style is not used.

This is a special case formatter intended to allow a human readable form of an Instant. The Instant class is designed to only represent a point in time and internally stores a value in nanoseconds from a fixed epoch of 1970-01-01Z. As such, an Instant cannot be formatted as a date or time without providing some form of time-zone. This formatter allows the Instant to be formatted, by providing a suitable conversion using ZoneOffset.UTC.

The format consists of:

The ISO_OFFSET_DATE_TIME where the instant is converted from ChronoField.INSTANT_SECONDS and ChronoField.NANO_OF_SECOND using the UTC offset. Parsing is case insensitive.

The returned formatter has no override chronology or zone. It uses the STRICT resolver style.

Compatible answered 29/7, 2020 at 15:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.