Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 DateTimeFormatter with optional part

Tags:

time

java-8

I have a String representing a date (with or without time) like 13/12/2017 or 13/12/2017 15:39:51

So i'm trying to use java 8 DateTimeFormatter with optional part.

That code works

LocalDateTime localDateTime = LocalDateTime.parse("13/12/2017 15:39:51",DateTimeFormatter.ofPattern("dd/MM/yyyy[ HH:mm:ss]"));
System.out.println(localDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
System.out.println(localDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")));

13/12/2017
15:39:51

But I don't understand why that one does not

LocalDateTime localDateTime = LocalDateTime.parse("13/12/2017",DateTimeFormatter.ofPattern("dd/MM/yyyy[ HH:mm:ss]"));

giving me

Exception in thread "main" java.time.format.DateTimeParseException: Text '13/12/2017' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2017-12-13 of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
...

And even with

LocalDateTime localDateTime = LocalDateTime.parse("13/12/2017",DateTimeFormatter.ofPattern("dd/MM/yyyy"));

it does not work with the same exception.

like image 632
tweetysat Avatar asked Jan 16 '18 11:01

tweetysat


People also ask

What is the difference between DateTimeFormatter and SimpleDateFormat?

DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.

Is DateTimeFormatter thread-safe Java?

A formatter created from a pattern can be used as many times as necessary, it is immutable and is thread-safe.

How do I use DateTimeFormatter with date?

DateTimeFormatter fmt = DateTimeFormatter. ofPattern("yyyy-MM-dd'T'HH:mm:ss"); System. out. println(ldt.

How do I format a date in Java 8?

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); System. out. println(sdf.


1 Answers

Use parseBest

When you use an optional component, you should parse using parseBest. Your application may be working using only parse, but then it's only by luck (because you're only parsing full inputs, not partial ones). With parseBest, you can properly handle various TemporalAccessor, which is the whole reason to use optional.

The decision of which TemporalAccessor is returned is rather simple: parseBest will try to match each TemporalQuery in order of argument. When any matches, the method returns that one. So make sure to go from most precise to less precise. Also, if none were matched, an exception will be thrown.

LocalDateTime dateTime;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy[ HH:mm:ss]");
TemporalAccessor temporalAccessor = formatter.parseBest("13/12/2017", LocalDateTime::from, LocalDate::from);
if (temporalAccessor instanceof LocalDateTime) {
  dateTime = (LocalDateTime)temporalAccessor;
} else {
  dateTime = ((LocalDate)temporalAccessor).atStartOfDay();
}
like image 75
Olivier Grégoire Avatar answered Sep 20 '22 12:09

Olivier Grégoire