Search code examples
javajava-timedate-parsinglocaldate

DateTimeFormatterBuilder#appendText(TemporalField, Map<Long,String>) throws exception when parsing


I'm trying to parse text that represents a LocalDate value with the IsoField.QUARTER_OF_YEAR using a DateTimeFormatter returned by the DateTimeFormatterBuilder#buildFormatter() method.

The problematic text is "20 Oct 2018 Q2". The quarter value ("Q2") is admittedly incorrect for a conventional calendar year, here "2018". However, I am working with a fiscal year which ends on June 30, so that the date "20 Oct 2018" would be in the fiscal year's second quarter.

The formatter is built with the following code:

TemporalQuery<LocalDate> query = LocalDate::from;
String pattern = “d MMM uuuu qqq”;
Locale locale = Locale.forLanguageTag("en-US");
TemporalField tf = IsoFields.QUARTER_OF_YEAR;
Map<Long, String> m = new Hashtable<>();
m.put(4L, “Q2”);
DateTimeFormatter formatter = new DateTimeFormatterBuilder()                                                                                
                                       .parseCaseInsensitive()
                                       .appendPattern(pattern)
                                       .appendText(tf, m)
                                       .toFormatter(locale);
TemporalAccessor value = formatter.parse(text, query)

Attempts to parse generate a DateTimeParseException with the error message: “Text '20 Oct 2018 Q2' could not be parsed at index 0”

I’ve tried changing the order in which the parseCaseInsensitive()appendText() methods are called. The exception is still thrown, although the specified index is 14 in one of the variations.

Possible reason for problem: The DateTimeFormatterBuilder#appendText(TemporalField, Map) method may work only in format operations, and not for parsing as here.

Thanks in advance for any ideas or help!


Solution

  • You try to parse the quarter year part twice - once per pattern instruction (using letter q) and once per builder-instruction (using method appendText). Solution: Remove the qqq-part in your pattern and use "d MMM uuuu ".

    Some remarks however:

    • Fiscal years are not supported at all.
    • Use better HashMap instead of outdated Hashtable.
    • The example code has special quotation marks instead of standard char (").
    • The parsed value is equivalent to LocalDate.of(2018, 10, 20) (and has no information about your special quarters).