jmspaggi
jmspaggi

Reputation: 117

DateTimeFormatter single digit month

I'm trying to parse a date where the month goes from 1 to 12 (And not from 01 to 12).

I'm trying this:

    System.out.println(DateTimeFormatter.ofPattern("[[MM][M]yyyy").parse("112019"));
    System.out.println(DateTimeFormatter.ofPattern("[[MM][M]yyyy").parse("82019"));

The first line works, the second fails.

Even Myyyy fails to parse the second line. I have not been able to find any pattern able to parse 82019 :(

[M][MM] as well as [MM][M] fail. Reading the documentation it says:

M/L month-of-year number/text 7; 07; Jul; July; J

So M is supposed to parse both 8 and 11.

Anyone has been able to get something working?

This works: System.out.println(DateTimeFormatter.ofPattern("M-yyyy").parse("8-2019")); But the data I got don't have any separation between the month and the year.

Upvotes: 2

Views: 672

Answers (3)

Anonymous
Anonymous

Reputation: 86148

    DateTimeFormatter yearMonthFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
            .appendValue(ChronoField.YEAR, 4)
            .toFormatter();

    System.out.println(YearMonth.parse("112019", yearMonthFormatter));
    System.out.println(YearMonth.parse("82019", yearMonthFormatter));

Output from this snippet is:

2019-11
2019-08

Unintuitively (but very practical in many other situations) a single pattern letter for a numerical field does not mean 1 digit, but as many digits as it takes. So M is not what we need here. What we do need instead is a DateTimeFormatterBuilder and its appendValue method, which comes in a number of overloaded versions. What we use for parsing fields that haven’t got any delimiter between them is known as adjacent value parsing. java.time can do this when all fields except the first have fixed widths, which you fulfil nicely.

I prefer to parse into a YearMonth, it’s a perfect match for the information in your strings, but that’s not the point here.

Link: Documentation of DateTimeFormatterBuilder.appendValue(TemporalField, int) explaining adjacent value parsing.

Upvotes: 3

Christian S.
Christian S.

Reputation: 982

Perhaps DateTimeFormatterBuilder is what you are looking for:

String s = "112019";
System.out.println(new DateTimeFormatterBuilder()
        .appendPattern("M")
        .appendValue(ChronoField.YEAR, 4)
        .toFormatter()
        .parse(s)
);

Upvotes: 4

Julian Durchholz
Julian Durchholz

Reputation: 420

If all of your dates are given in the format you provided, consider isolating the values like so:

String s = "112019";
int yearIndex = s.length() - 4;
String pretty = s.substring(0, yearIndex) + " " + s.substring(yearIndex);
System.out.println(DateTimeFormatter.ofPattern("[M] yyyy").parse(pretty));

Upvotes: 2

Related Questions