I'm trying to parse a date time string using java 8 DateTime API.
The string to parse contains date, month, year and AM/PM marker such as 17/02/2015 PM
.
I use the following pattern: dd/MM/yyyy aa
and I expect the parsed LocalDateTime time part to be set at 12:00:00
or 00:00:00
depending on the AM/PM marker.
Using the former java.text.SimpleDateFormat
API, the parsing works as expected using this pattern.
But when i use java 8 DateTime API and run the following code:
LocalDateTime.parse("17/02/2015 PM", DateTimeFormatter.ofPattern("dd/MM/yyyy aa"));
I got the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: Too many pattern letters: a
at java.time.format.DateTimeFormatterBuilder.parseField(DateTimeFormatterBuilder.java:1765)
at java.time.format.DateTimeFormatterBuilder.parsePattern(DateTimeFormatterBuilder.java:1604)
at java.time.format.DateTimeFormatterBuilder.appendPattern(DateTimeFormatterBuilder.java:1572)
at java.time.format.DateTimeFormatter.ofPattern(DateTimeFormatter.java:534)
If i switch the pattern to dd/MM/yyyy a
then i got the folowing exception:
Exception in thread "main" java.time.format.DateTimeParseException: Text '17/02/2015 PM' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {AmPmOfDay=1},ISO resolved to 2015-02-17 of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {AmPmOfDay=1},ISO resolved to 2015-02-17 of type java.time.format.Parsed
at java.time.LocalDateTime.from(LocalDateTime.java:461)
at java.time.LocalDateTime$$Lambda$7/474675244.queryFrom(Unknown Source)
at java.time.format.Parsed.query(Parsed.java:226)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
... 2 more
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {AmPmOfDay=1},ISO resolved to 2015-02-17 of type java.time.format.Parsed
at java.time.LocalTime.from(LocalTime.java:409)
at java.time.LocalDateTime.from(LocalDateTime.java:457)
... 5 more
It's also weird that when i do the reverse operation, format, it works fine:
System.out.println(LocalDateTime.of(2015, 02, 17, 0, 0, 0).format(DateTimeFormatter.ofPattern("dd/MM/yyyy a")));
System.out.println(LocalDateTime.of(2015, 02, 17, 12, 0, 0).format(DateTimeFormatter.ofPattern("dd/MM/yyyy a")));
respectively prints 17/02/2015 AM
and 17/02/2015 PM
.
The javadoc for java.time.DateTimeFormatter
says (§Resolving, step #6):
- A LocalTime is formed if there is at least an hour-of-day available. This involves providing default values for minute, second and fraction of second.
What i understand is that the field hour-of-day is mandatory to parse a LocalDateTime... Isn't there any way to parse the time part only using the AM/PM field only?
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); System. out. println(sdf. parse(dtf.
Java 8 provides ZonedDateTime when we need to deal with time-zone-specific date and time. The ZoneId is an identifier used to represent different zones. There are about 40 different time zones, and the ZoneId represents them as follows. Another way to work with time zone is by using OffsetDateTime.
LocalTime is an immutable class whose instance represents a time in the human readable format. It's default format is hh:mm:ss. zzz.
You can set the default values for unavailable fields via DateTimeFormatterBuilder.parseDefaulting
:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("dd/MM/yyyy a")
.parseDefaulting(ChronoField.HOUR_OF_AMPM, 0) // this is required
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) // optional, but you can set other value
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) // optional as well
.toFormatter();
System.out.println(LocalDateTime.parse("17/02/2015 PM", formatter)); // 2015-02-17T12:00
System.out.println(LocalDateTime.parse("17/02/2015 AM", formatter)); // 2015-02-17T00:00
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