Reputation: 5031
I have timestamp in various format, example:
2018-07-21T00:50:39
2017-11-20T23:18:27.529Z
I need to parse them to java.util.Date, and have tried the following approach, they both worked for the first format but failed the second one.
Here are the methods I tried and it's error:
1.
private Date try3(String dateString) {
return Date.from(Instant.parse(dateString).atZone(ZoneId.of("UTC")).toInstant());
}
it failed at first format, error:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:28' could not be parsed at index 19
2.
private Date try2(String dateString) {
return Date.from(LocalDateTime.parse(dateString).atZone(ZoneId.of("UTC")).toInstant());
}
for second format, this method throw error:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:27.529Z' could not be parsed, unparsed text found at index 23
3:
private Date try1(String dateString) {
return Date.from(ZonedDateTime.parse(dateString,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(ZoneId.of("UTC"))).toInstant());
}
for the second format, the above method throw error:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:27.529Z' could not be parsed, unparsed text found at index 19
I eventually ended up with Joda library:
private Date try4(String dateString) {
return new DateTime(dateString).withZone(DateTimeZone.UTC).toDate();
}
But really is there any way to do this in Java time library?
Upvotes: 0
Views: 134
Reputation: 86389
You always want to obtain the same type, and I seem to understand that if no offset is in the string, you want UTC (it’s important to be clear about this). I suggest specifying a formatter with optional UTC offset and a default of UTC (zero offset) in case there isn’t any offset in the string:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("[X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
String withoutZ = "2018-07-21T00:50:39";
Instant anInstant = formatter.parse(withoutZ, Instant::from);
System.out.println(anInstant);
String withZ = "2017-11-20T23:18:27.529Z";
Instant anotherInstant = formatter.parse(withZ, Instant::from);
System.out.println(anotherInstant);
Output:
2018-07-21T00:50:39Z 2017-11-20T23:18:27.529Z
The square brackets in the format pattern string [X]
denote that offset X is optional. The presence and absence of decimals on the seconds is handled by ISO_LOCAL_DATE_TIME
.
I hope that you are aware that the Date
class is poorly designed and long outdated, so generally you shouldn’t want one, and that you are only asking for one because you indispensably need one for a legacy API that you cannot change just now. In this case do the final conversion from Instant
as in your question.
The techniques generally used for variable date/time formats include:
.endsWith("Z")
as already suggested in Basil Bourque’s answer.DateTimeFormatterBuilder.parseDefaulting()
for parts that may be absent from the parsed string.DateTimeFormatter.parseBest()
.As you have seen, I am using items 3. and 4. here.
Upvotes: 1
Reputation: 340230
This has been covered countless times already. So search Stack Overflow for more info.
Never use Date
or Calendar
. Use only java.time. Likewise, Joda-Time is also supplanted by java.time (both being led by the same man, Stephen Colebourne).
Both your string inputs are in standard ISO 8601 format. The java.time classes use these formats by default when parsing/generating strings.
The first lacks an indicator of offset-from-UTC or time zone, so it does not represent a moment.
LocalDateTime.parse( "2018-07-21T00:50:39" )
The second in Z
which means UTC, and is pronounced “Zulu”.
Instant.parse( "2017-11-20T23:18:27.529Z" )
To handle both formats in one method, search the input string for the presence of the Z
and branch accordingly. Also, trap for the exception in case you receive unexpected inputs.
If you must have a java.util.Date
object, see that class JavaDoc for new methods from
& to…
on the old classes that convert to/from the java.time classes. As I said, all this has been covered many many times, so search for more info.
Upvotes: 1