Peter Penzov
Peter Penzov

Reputation: 1754

Convert Date from JavaScript to Java

I have this Date value in angular 6 application:

expires_at: Date;

In Java getter I use String to get the value:

private String expires_at;

But when I convert using this code:

From String to LocalDateTime

terminals.setExpires_at(LocalDateTime.parse(terminalDTO.getExpires_at()));

From LocalDateTime to String:

terminalNewDTO.setExpires_at(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(terminals.getExpires_at()));

I get this error:

create] due to exception [Text '2019-02-19T01:00:00.000Z' could not be parsed, unparsed text found at index 23]
20:55:43,494 INFO  [stdout] (default task-1) java.time.format.DateTimeParseException: Text '2019-02-19T01:00:00.000Z' could not be parsed, unparsed text found at index 23
20:55:43,494 INFO  [stdout] (default task-1)    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
20:55:43,494 INFO  [stdout] (default task-1)    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
20:55:43,495 INFO  [stdout] (default task-1)    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
20:55:43,495 INFO  [stdout] (default task-1)    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:477)
20:55:43,496 INFO  [stdout] (default task-1)    at deployment.datalis_admin.war//org.datalis.admin.backend.mapper.TerminalsMapperImpl.map(TerminalsMapperImpl.java:98)
20:55:43,496 INFO  [stdout] (default task-1)    at deployment.datalis_admin.war//org.datalis.admin.backend.restapi.TerminalController.create(TerminalController.java:104)
20:55:43,496 INFO  [stdout] (default task-1)    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
20:55:43,497 INFO  [stdout] (default task-1)    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
20:55:43,497 INFO  [stdout] (default task-1)    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
20:55:43,497 INFO  [stdout] (default task-1)    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
20:55:43,497 INFO  [stdout] (default task-1)    at deployment.datalis_admin.war//org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)

Do you know how I can solve this issue?

This is the date value: 2/20/19, 3:00 AM which I try to send.

Upvotes: 4

Views: 1483

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 340230

UTC

The Z means an offset-from-UTC of zero hours-minutes-seconds. In other words, UTC itself. The Z is pronounced “Zulu”.

Parse using Instant class, which represents a moment in UTC.

Instant instant = Instant.parse( "2019-02-19T01:00:00.000Z" ) ;

That input string is in standard ISO 8601 format. The java.time classes use ISO 8601 formats be default for both parsing and generating strings.

instant.toString() // generates a ISO 8601 string.

Two hours ahead of UTC

You said in the Question:

This is the date value: 2/20/19, 3:00 AM

If the original value was 3 AM, apparently it was in a time zone two hours ahead of UTC. That could be any of several time zones, as you can see in this list in Wikipedia (that list may not be quite up-to-date, beware).

I will arbitrarily go with with Africa/Tripoli.

ZoneId z = ZoneId.of( "Africa/Tripoli" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.

Both instant and zdt represent the very same moment, the same simultaneous point on the timeline. That one moment is being viewed through the wall-clock time used by the peoples of two different regions.

Imagine someone in Libya calls someone in Iceland. While chatting they both look up at the clock on their respective walls. Iceland clocks use an offset-from-UTC of zero, while in Libya they are two hours ahead of UTC. So 3 AM in Libya is 1 AM in Iceland.

See this code run live at IdeOne.com.

instant.toString(): 2019-02-19T01:00:00Z

zdt.toString(): 2019-02-19T03:00+02:00[Africa/Tripoli]

LocalDateTime class is not for moment

From LocalDateTime to String:

Never use LocalDateTime when tracking moments. A LocalDateTime is merely a date and a time-of-day, and nothing more. Without the context of a time zone or offset-from-UTC, a LocalDateTime cannot represent a moment. It represents potential moments along a range of about 26-27 hours, the current range of time zones around the globe.

A LocalDateTime is like saying “noon on the 23rd of January this year”. Do you mean noon in Tokyo Japan or Kolkata India? Or maybe Paris France? Montréal Québec? Noon in these various places happen at different moments, with hours elapsed between each.

The “Local” in LocalDateTime means any locality, or every locality, but does not mean any particular locality.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 13

Yaroslav Nudnenko
Yaroslav Nudnenko

Reputation: 290

You also could use:

String expires_at = "2/20/19, 3:00 AM";
SimpleDateFormat parser = new SimpleDateFormat("MM/dd/yyyy, h:mm a"); 
Date date = parser.parse(expires_at); 

Upvotes: 1

Related Questions