I have a simple problem : I want to parse Java strings in format "yyyyMMdd"
strictly, so that "19800229"
is a valid date, but "19820229"
is not. Assume these are AD dates from the normal Gregorian calendar.
I am trying to use the new java.time
package from JDK 8 to solve this problem, but it is proving more complicated than hoped. My current code is:
private static final DateTimeFormatter FORMAT = DateTimeFormatter
.ofPattern("yyyyMMdd").withChronology(IsoChronology.INSTANCE)
.withResolverStyle(STRICT);
public static LocalDate parse(String yyyyMMdd) {
return LocalDate.parse(yyyyMMdd, FORMAT);
}
However, parsing a valid date such as "19800228" produces what to me is an incomprehensible error:
java.time.format.DateTimeParseException: Text '19820228' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=2, DayOfMonth=28, YearOfEra=1982},ISO of type java.time.format.Parsed
How do I use java.time.format.DateTimeFormatter
to solve my simple use case?
I'm editing to limit what kind of string will be considered valid by using a custom formatter created with a DateTimeFormatterBuilder.
2/29/1982 is invalid and would throw the following:
A date of 19800228-5000 would work with BASIC_ISO_DATE because it allows the optional offset which you don't want allowed. My CUSTOM_BASIC_ISO_DATE formatter will not allow that and throw the following:
Note, if you are sure of the string length, yyyyMMdd then you could always work with the substring of first 8 chars to negate the need for the resolver. However that is two different things. The resolver will flag invalid date formats on input and the substring would of course just strip the extra chars out.
Java 8 uses
uuuu
for year, notyyyy
. In Java 8,yyyy
means "year of era" (BC or AD) and the error message complains that MonthOfYear, DayOfMonth and YearOfEra is not enough information to construct the date because era is not known.To fix that, use
uuuu
in your format string, e.g.DateTimeFormatter.ofPattern("uuuuMMdd")
Or, if you want to keep using
yyyy
, you can set the default era, e.g.Try using format "uuuuMMdd" instead.