When I pass a Javascript Date to a JAX-RS service I receive:
- In case the target field is LocalDate: Text '2018-06-04T22:00:00.000Z' could not be parsed, unparsed text found at index 10". The BackEnd is ok with "2018-06-04", I tried with Postman.
- In case the target field is LocalDateTime: Text '2019-04-02T20:16:24.999Z' could not be parsed, unparsed text found at index 23. The BackEnd is ok with "2019-04-02T20:16:24", I tried with Postman.
The information i pass to the BackEnd e from a Angular Material Datepicker ponent that I map on a javascript Date object.
I understand that the string has informations that the BackEnd do not aspect but I don't know how to pass the correct/modified value before call the POST.
Should I pass a String instead of a Date object? Is that the correct approach?
Is there a way from a date in the format "2018-06-04T22:00:00.000Z" or "2018-06-05T00:00:00.000Z" to be passed to a LocalDate and a LocalDateTime?
I used LocalDate and LocalDateTime because I do not want to deal with timezone. The value are supposed to be always the same even if I change the timezone.
Before I had a problem because there was a 1 hour difference between the server and the client. So when i used to pick a date from the web server it could happen that the client would see the day before on the ponent becasue it was going back 1 hour from midnight.
When I pass a Javascript Date to a JAX-RS service I receive:
- In case the target field is LocalDate: Text '2018-06-04T22:00:00.000Z' could not be parsed, unparsed text found at index 10". The BackEnd is ok with "2018-06-04", I tried with Postman.
- In case the target field is LocalDateTime: Text '2019-04-02T20:16:24.999Z' could not be parsed, unparsed text found at index 23. The BackEnd is ok with "2019-04-02T20:16:24", I tried with Postman.
The information i pass to the BackEnd e from a Angular Material Datepicker ponent that I map on a javascript Date object.
I understand that the string has informations that the BackEnd do not aspect but I don't know how to pass the correct/modified value before call the POST.
Should I pass a String instead of a Date object? Is that the correct approach?
Is there a way from a date in the format "2018-06-04T22:00:00.000Z" or "2018-06-05T00:00:00.000Z" to be passed to a LocalDate and a LocalDateTime?
I used LocalDate and LocalDateTime because I do not want to deal with timezone. The value are supposed to be always the same even if I change the timezone.
Before I had a problem because there was a 1 hour difference between the server and the client. So when i used to pick a date from the web server it could happen that the client would see the day before on the ponent becasue it was going back 1 hour from midnight.
Share Improve this question edited Apr 2, 2019 at 22:31 Lorenzo asked Apr 2, 2019 at 20:23 LorenzoLorenzo 211 silver badge5 bronze badges 2-
The string
2018-06-04T22:00:00.000Z
can be correctly parsed byInstant
,ZonedDateTime
andOffsetDateTime
. I'd suggest usingZonedDateTime
for most flexible time zone parsing, and so you can easily obtainLocalDateTime
andLocalDate
from it. – Andreas Commented Apr 2, 2019 at 20:27 -
Warning: Note that
2018-06-04T22:00:00.000Z
is probably supposed to be2018-06-05
in aUTC+02:00
time zone. If so, you'd likely want to apply that time zone first, before obtaining theLocalDate
andLocalDateTime
values, so the "local" is appropriate for that time zone. --- To do that, I'd suggest usingInstant.parse("2018-06-04T22:00:00.000Z").atOffset(ZoneOffset.of("+2")).toLocalDate()
– Andreas Commented Apr 2, 2019 at 20:29
1 Answer
Reset to default 7You seem to be confusing the various date-time types.
ISO 8601
The string 2018-06-04T22:00:00.000Z
is in standard ISO 8601 format. The Z
on the end means UTC, and is pronounced Zulu.
The ISO 8601 formats are wisely designed. They are easy to parse by machine. And they are easy to read by humans across cultures. Their primary purpose is to municate date-time values in a textual format. You should indeed be using strings in these formats for exchanging date-time values between systems.
Instant
Parse as an Instant
in the java.time classes.
Instant instant = Instant.parse( "2018-06-04T22:00:00.000Z" ) ;
LocalDate
The LocalDate
class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
Specify a proper time zone name in the format of Continent/Region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 2-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code bees ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
So you need to decide by what time zone you want to perceive the moment in UTC as a date and time-of-day.
The ISO 8601 format for a date-only value is YYYY-MM-DD.
String output = ld.toString() ; // Example: 2019-01-23
…and…
LocalDate ld = LocalDate.parse( "2019-01-23" ) ;
To generate such a string in JavaScript, see Format JavaScript Date to yyyy-mm-dd.
OffsetDateTime
If you want UTC
itself, convert from Instant
to OffsetDateTime
. Then extract the date alone.
OffsetDateTime odt = instant.atOffset( ZoneOffsetUTC ) ; // Convert to the more flexible `OffsetDateTime` class from `Instant` class.
LocalDate ld = odt.toLocalDate() ; // Extract a date-only value.
ZonedDateTime
If you want a particular time zone, apply a ZoneId
to get a ZonedDateTime
. Then extract the date alone.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Adjust from UTC to a time zone.
LocalDate ld = zdt.toLocalDate() ; // Extract a date-only value, dropping the time-of-day and the time zone.
By the way, note that ZonedDateTime
class in its toString
method extends the ISO 8601 format by appending the name of the time zone in square brackets. A wise addition, but may not be handled properly by some other systems.
LocalDateTime
The LocalDateTime
class is the wrong type to be using for an input such as 2018-06-04T22:00:00.000Z
or 2019-04-02T20:16:24.999Z
. These string inputs represent a moment, a specific point on the timeline. The LocalDateTime
class purposely lacks any concept of time zone or offset, so it cannot represent a moment.
People frequently misunderstand the nature of LocalDateTime
. The “Local” means any locality or every locality, but not a particular locality. For a moment in a specific locality, use ZonedDateTime
.
For more info, see What's the difference between Instant and LocalDateTime?.
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 pliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.