1

I'm handling a Minguo date parsing problem. Our system representing the year BEFORE ROC with negative sign -.

After some reading, we came up a working solution:

Map<Long, String> eraSign = new HashMap<>();
eraSign.put((long) MinguoEra.BEFORE_ROC.getValue(), "-");
eraSign.put((long) MinguoEra.ROC.getValue(), "");

DateTimeFormatter dtf= new DateTimeFormatterBuilder().parseStrict() // Strictly parsing
    .appendText(ChronoField.ERA, eraSign).appendPattern("yyyMMdd") // date pattern with era prefix
    .parseDefaulting(ChronoField.ERA, MinguoEra.ROC.getValue()) // default to Minguo era
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) // default to January
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) // default to 1st
    .toFormatter().withChronology(MinguoChronology.INSTANCE);

dtf.parse("-0170417"); // AD 1895/04/17

However, this method limit us putting the era at somewhere fixed, and we can't parse date like 17-April, -17 unless we create new formatter with new rule .appendPattern("d-MMM, ").appendText(ERA, eraSign).appendPattern("y").

Instead of predefining all possible patterns, I'm searching a way processing the minus sign from pattern directly, without calling .appendText(TemporalField, Map<Long, String>):

// something like this
DateTimeFormatter dtf= new DateTimeFormatterBuilder().parseStrict() // Strictly parsing
    .appendPattern("GyyyMMdd") // full date pattern
    .parseDefaulting(ChronoField.ERA, MinguoEra.ROC.getValue()) // default to Minguo era
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) // default to January
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) // default to 1st
    .toFormatter().withChronology(MinguoChronology.INSTANCE);
dtf.parse("-0170417");

// or even shorter:
DateTimeFormatter.ofPattern("GyyyMMdd").parse("-0170417");

The pattern may be GyyyMMdd, G yyy, G or whatever (provided by caller). The era pattern symbol can be the default G or something else we agreed.

It seems that changing Locale doesn't work. The Locale.Builder doesn't contain any information related to DateTimeFormat, neither.

How can I parse the input with pattern directly?

Pin Gu
  • 133
  • 1
  • 3
  • 9
  • 2
    It sounds like you are doing the right thing here. From the documentation of `appendText`: "For example, a legacy application might require or supply the months of the year as "JNY", "FBY", "MCH" etc. These do not match the standard set of text for localized month names. Using this method, a map can be created which defines the connection between each value and the text" So it is made for exceptional cases like this. – Sweeper Feb 17 '21 at 09:11
  • @Sweeper We have aware that. The thing is, since this pattern appear again and again across our system, is it possible making it something reusable? I am considering creating custom locale, but this must be the wrong way because I can't find anything configurable. – Pin Gu Feb 17 '21 at 10:12
  • 2
    Maybe write your own `ofPattern` method that only handles `G`s differently (call `appendText(ChronoField.ERA, eraSign)` when you encounter `G`), and delegates everything else to `DateTimeFormatter` (call `appendPattern` when you encounter anything else)? Not sure if this is actually a good solution, just something that I thought of. – Sweeper Feb 17 '21 at 10:15
  • Does this specific format pattern, `GyyyMMdd`, appear again and again, or different patterns that use `G` to mean an optional minus sign for before ROC? You probably want to add this information to your question so that new readers are also aware (and take it into account if providing an answer). – Ole V.V. Feb 17 '21 at 17:24
  • 2
    This won’t help you, I just observed. `DateTimeFormatter.ofPattern("uuuMMdd").withChronology(MinguoChronology.INSTANCE)` parses your string with a minus, but into 1894-04-17, one year too early, because java.time insist that there must be a year 0. *For every complex problem there is an answer that is clear, simple, and wrong.* (H. L. Mencken) – Ole V.V. Feb 17 '21 at 17:28
  • @Sweeper Sadly the DateTimeFormatterBuilder doesn't provide a handy way extending self-defined symbol without overriding entire `parsePattern(String)`. We will put this way as the last resort. – Pin Gu Feb 18 '21 at 01:57
  • @OleV.V. Yes, the `u` is more like to the concept "how many years passed after the beginning". Related question https://stackoverflow.com/a/29014580/ – Pin Gu Feb 18 '21 at 01:57

0 Answers0