With Java 8's new date time library, the way to parse strings into dates is to use the DateTimeFormatter
. LocalDate
, LocalTime
and LocalDateTime
all have a static parse method that takes in a String and a formatter. A potential gotcha is that if your DateTimeFormat does not contain a time portion (or for DateTime, a date portion) you end up getting a parse error even if your pattern matches.
Example
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-DD");
LocalDateTime dt = LocalDateTime.parse("2016-01-11", formatter);
This will throw a DateTimeParseException
(as discussed here) with the message
java.time.format.DateTimeParseException:
Text '2016-01-11' could not be parsed:
Unable to obtain LocalDateTime from TemporalAccessor
This is a somewhat unhelpful error message as the text can be parsed since it matches the pattern. Rather the error has to do with the fact that it cannot create the time portion of LocalDateTime. Refactoring the code to the below works:
LocalDateTime ldt = LocalDate.parse("2016-01-11", formatter).atStartOfDay());
My question is, say you had a generic method like such
public static LocalDateTime getDate(String s, DateTimeFormatter format) {
...
}
Is there a way to determine which static parse method you would need to call to coerce the string into a LocalDateTime by applying some default logic? e.g. If date only use midnight, if time only use today, etc.
DateTimeFormatter fmt = DateTimeFormatter. ofPattern("yyyy-MM-dd'T'HH:mm:ss"); System. out. println(ldt.
DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.
A formatter created from a pattern can be used as many times as necessary, it is immutable and is thread-safe. The count of pattern letters determines the format.
format. DateTimeFormatterBuilder Class in Java. DateTimeFormatterBuilder Class is a builder class that is used to create date-time formatters. DateTimeFormatter is used as a Formatter for printing and parsing date-time objects.
I think you have the question in reverse. You don't want to determine if a formatter uses only a date or a date/time. You create a formatter based on what you should parse and on what you intend to store the result to. Obviously, if you create a formatter that does not handle the time part, using it to parse into a LocalDateTime
is a misconception.
If you need to parse dates that can arrive with two formats like "yyyy-MM-dd"
or "yyyy-MM-dd HH:mm:ss"
(with a time part), it is not up to the parsing to determine what it should do but up to the formatter to provide defaults in the case that there is no time.
With Java Time, this is done with optional sections and default values. For example, the pattern "yyyy-MM-dd[ HH:mm:ss]"
will be able to parse date String (like "2016-01-11"
) and date/time String (like "2016-01-11 20:10:10"
). If you will store that into a LocalDateTime
, you will need to provide default values in case there is no time component. This is done with parseDefaulting(field, value)
: this will tell the formatter to return the given default value for that chrono field if it was not already set.
The following code creates such a formatter and defaults the time part to midnight.
public static void main(String[] args) {
DateTimeFormatter formatter =
new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd[ HH:mm:ss]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
LocalDateTime dt1 = LocalDateTime.parse("2016-01-11", formatter);
LocalDateTime dt2 = LocalDateTime.parse("2016-01-11 20:10:10", formatter);
}
This logic could of course be extended to parse time only String and defaulting the date component to the current date.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With