4

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.

7
  • You're using "Z" for "Zulu time"/UTC? Commented Feb 24, 2019 at 21:20
  • I don't know. This is from date picker. Commented Feb 24, 2019 at 21:21
  • You could use OffsetDateTime date = OffsetDateTime.parse("2019-02-19T01:00:00.000Z", DateTimeFormatter.ISO_OFFSET_DATE_TIME); Commented Feb 24, 2019 at 21:24
  • I don’t believe you get the same stacktrace from the second code line added in your recent edit. Please quote exact stacktrace for each (or post a new question with the new issue). Commented Feb 25, 2019 at 17:33
  • OneLiner ~ ZonedDateTime.parse("2019-02-19T01:00:00.000Z", DateTimeFormatter.ISO_ZONED_DATE_TIME).toLocalDateTime(); Commented Mar 4, 2019 at 17:31

2 Answers 2

13

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.

Sign up to request clarification or add additional context in comments.

6 Comments

@PeterPenzov I added a code example. And, FYI, this has been addressed many many times already on Stack Overflow. Search before posting, and search for more detailed discussion and more examples.
Can you show me into my code how to use your solution, please?
I suppose the quick fix would be terminals.setExpires_at(LocalDateTime.parse(terminalDTO.getExpires_at(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));. But please do consider if you can use Instant or OffsetDateTime instead of LocalDateTime in you app.
It turns out that I have one more case. Code is updated.
I think there is more to think of here. Its better to use a DatePipe in angualr ts , and convert the date to a standard format your application always expect. Use of Instant.parse() works only for the ISO_INSTANT formats (your current case). If the format changes by any chance in your UI, the code will break in back-end. The best approach to this will be always use UTC timestamps for service data.
|
1

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); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.