Convert Month Number to Name and Back in Java

Convert month number to name in Java with Month.getDisplayName(), and parse full or short month names back to numbers in any locale.

Conversion map between the month number 1, the Month constant JANUARY, the display names January and Jan, and back with Month.of, getDisplayName, getValue and a DateTimeFormatter

To convert month number to name in Java, we call Month.of(number).getDisplayName(TextStyle.FULL, locale), and to convert a month name back to its number, we parse the name with a DateTimeFormatter using the pattern MMMM or MMM and call getValue() on the resulting Month. Both directions use the java.time.Month enum, which numbers the months from 1 for January to 12 for December.

Month data reaches our code in both forms. A report shows “January” where the database stores 1, and a bank statement exported as CSV writes “Mar” where our code needs the number 3.

The following example converts in both directions with explicit locales.

String full = Month.of(1).getDisplayName(TextStyle.FULL, Locale.US);              // "January"
String abbr = Month.of(1).getDisplayName(TextStyle.SHORT, Locale.US);              // "Jan"
String constant = Month.of(1).name();                                              // "JANUARY"
int fromName = Month.valueOf("MARCH").getValue();                                  // 3
Month parsed = Month.from(DateTimeFormatter.ofPattern("MMM", Locale.US).parse("Mar"));   // MARCH
int fromAbbr = parsed.getValue();                                                  // 3

Notice that the enum constant name JANUARY is not the display name, and that parsing “Mar” needs a locale, because month names differ by language. We cover numbers to names, names to numbers, abbreviations, locale traps and a CSV import, and finish with the zero-based months of the legacy Calendar class.

1. Convert Month Number to Name

When we get the month as a number such as 1, we can turn it into a name in three ways.

  • The full name “January” is the text for display.
  • The constant name “JANUARY” is the name of the java.time.Month enum constant, which suits logs, JSON and configuration files.
  • The abbreviation “Jan” is the short form for tables, charts and narrow screens.

Each conversion method obtains a Month constant with Month.of(monthNumber) and reads the text with getDisplayName() or name(). The locale is a parameter, because a server’s default locale is not the user’s language.

Conversion map between the month number 1, the Month constant JANUARY, the display names January and Jan, and back with Month.of, getDisplayName, getValue and a DateTimeFormatter
Every conversion goes through the Month enum
static String monthNumberToAbbr(int monthNumber, Locale locale) {
    return Month.of(monthNumber).getDisplayName(TextStyle.SHORT, locale);
}

static String monthNumberToFullName(int monthNumber, Locale locale) {
    return Month.of(monthNumber).getDisplayName(TextStyle.FULL, locale);
}

static String monthNumberToName(int monthNumber) {
    return Month.of(monthNumber).name();
}
String abbr = monthNumberToAbbr(1, Locale.US);               // "Jan"
String full = monthNumberToFullName(1, Locale.US);           // "January"
String name = monthNumberToName(1);                          // "JANUARY"
String bad = monthNumberToFullName(13, Locale.US);           // DateTimeException: Invalid value for MonthOfYear: 13

For a number outside 1 to 12, Month.of() throws a DateTimeException. When the number comes from user input or a file, we check the range before the call or catch the exception and report the bad row.

If the code already holds a date, we read the month from it with getMonth() or format it with the pattern MMMM, without going through the number.

LocalDate statementDate = LocalDate.of(2026, 3, 5);
Month month = statementDate.getMonth();                                                 // MARCH
int monthNumber = statementDate.getMonthValue();                                        // 3
String monthText = statementDate.format(DateTimeFormatter.ofPattern("MMMM", Locale.US));  // "March"

1.1. Month Names in Other Languages

The TextStyle sets the length of the name and the locale sets the language. On JDK 25, the names come from the Unicode CLDR data, and the abbreviations are not always three letters long.

TextStyleLocale.USLocale.UKLocale.GERMANLocale.FRENCH
FULL for JanuaryJanuaryJanuaryJanuarjanvier
SHORT for JanuaryJanJanJan.janv.
SHORT for SeptemberSepSeptSept.sept.
NARROW for JanuaryJJJJ

Some languages also use a different form of the month name inside a date than on its own. In Czech, the full name of January is “ledna” in a date and “leden” as a standalone name, so a column header uses TextStyle.FULL_STANDALONE or the pattern LLLL.

Locale czech = Locale.forLanguageTag("cs");
String inDate = Month.JANUARY.getDisplayName(TextStyle.FULL, czech);                // "ledna"
String onItsOwn = Month.JANUARY.getDisplayName(TextStyle.FULL_STANDALONE, czech);   // "leden"

2. Converting Month Name to Month Number

To convert a month name into its number, we choose the approach by the kind of input we expect.

  • For the constant name in English, such as “January” or “MARCH”, the method Month.valueOf() takes the uppercase name and returns the enum constant.
  • For any localized full name or abbreviation, a DateTimeFormatter with the pattern MMMM or MMM and the right locale parses the text into a Month.
static int monthNameToNumber(String monthName) {
    return Month.valueOf(monthName.strip().toUpperCase(Locale.ROOT)).getValue();
}
int january = monthNameToNumber("January");    // 1
int march = monthNameToNumber("march");         // 3
int jan = monthNameToNumber("Jan");             // IllegalArgumentException: No enum constant java.time.Month.JAN

The method fails for “Jan” and for every non-English name, because valueOf() knows only the twelve constant names. We use Locale.ROOT in toUpperCase(), because in Turkish the uppercase of “i” is a dotted capital letter, which would break names such as “April”.

A formatter covers abbreviations and other languages. A plain formatter is case-sensitive, so we build one with parseCaseInsensitive(), try the full name before the abbreviation, and return an OptionalInt for unknown text.

static OptionalInt monthNumber(String text, Locale locale) {
    if (text == null || text.isBlank()) {
        return OptionalInt.empty();
    }
    for (String pattern : List.of("MMMM", "MMM")) {
        DateTimeFormatter format = new DateTimeFormatterBuilder()
                .parseCaseInsensitive().appendPattern(pattern).toFormatter(locale);
        try {
            return OptionalInt.of(Month.from(format.parse(text.strip())).getValue());
        } catch (DateTimeParseException e) {
            // try the next pattern
        }
    }
    return OptionalInt.empty();
}
OptionalInt fromFull = monthNumber("January", Locale.US);         // OptionalInt[1]
OptionalInt fromAbbr = monthNumber("SEP", Locale.US);             // OptionalInt[9]
OptionalInt fromGerman = monthNumber("januar", Locale.GERMAN);    // OptionalInt[1]
OptionalInt unknown = monthNumber("Smarch", Locale.US);           // OptionalInt.empty

The old version of this method compared the input with the first three letters of each constant name. That works only for English and fails for abbreviations such as “janv.” in French, whereas the formatter uses the same CLDR data that produces the names.

3. Converting Month Abbreviation to Full Name

A short name such as “Apr” sometimes has to become “April”, for example when a report shows the full name. We combine the two directions, parsing the abbreviation into a Month and asking for the FULL display name in the same locale.

static Optional<String> monthAbbrToFullName(String abbreviation, Locale locale) {
    OptionalInt number = monthNumber(abbreviation, locale);
    if (number.isEmpty()) {
        return Optional.empty();
    }
    return Optional.of(Month.of(number.getAsInt()).getDisplayName(TextStyle.FULL, locale));
}
Optional<String> april = monthAbbrToFullName("Apr", Locale.US);           // Optional[April]
Optional<String> janvier = monthAbbrToFullName("janv.", Locale.FRENCH);    // Optional[janvier]
Optional<String> nothing = monthAbbrToFullName("Xyz", Locale.US);          // Optional.empty

4. Reading Month Names From a Bank Statement CSV

A personal finance app imports bank statements in which the period column holds values such as “Sep 2026”. The month and the year together form a YearMonth, so we parse the column with the pattern MMM uuuu and keep the year instead of converting only the month.

DateTimeFormatter usPeriod = DateTimeFormatter.ofPattern("MMM uuuu", Locale.US);
YearMonth september = YearMonth.parse("Sep 2026", usPeriod);                                 // 2026-09
int monthNumber = september.getMonthValue();                                                 // 9
YearMonth ukSeptember = YearMonth.parse("Sept 2026", DateTimeFormatter.ofPattern("MMM uuuu", Locale.UK));   // 2026-09
YearMonth ukFails = YearMonth.parse("Sep 2026", DateTimeFormatter.ofPattern("MMM uuuu", Locale.UK));        // DateTimeParseException

The locale of the formatter must match the locale that wrote the file, because CLDR data abbreviates September as “Sept” in British English and as “Sep” in US English. A file from a UK bank parsed with Locale.US, or the other way round, fails for September only, and tests that use other months do not catch the bug.

5. Month Numbers in Calendar and Legacy Code

The legacy Calendar.MONTH field counts months from 0, so January is 0 and December is 11, and DateFormatSymbols.getMonths() returns an array of 13 names with an empty last element. When we read a month from such code, we add 1 and continue with Month.

Calendar calendar = new GregorianCalendar(2026, Calendar.MARCH, 5);
int legacyMonth = calendar.get(Calendar.MONTH);                    // 2
Month month = Month.of(legacyMonth + 1);                           // MARCH
int symbols = DateFormatSymbols.getInstance(Locale.US).getMonths().length;   // 13

Converting the whole Calendar or Date to a LocalDate is the cleaner fix, because getMonthValue() on the result returns 1 to 12. The other parts of a date are covered in getting the year, month and day from a date.

6. Month Name and Number FAQs

Zero-based months, the current month and parsing errors come up most often after these conversions.

6.1. Is January 0 or 1 in Java?

In java.time, January is 1, as in Month.JANUARY.getValue() and LocalDate.getMonthValue(). In the legacy Calendar class, Calendar.JANUARY is 0. The method ordinal() of the Month enum also returns 0 for January, so we never use it as a month number.

6.2. How do I get the name of the current month?

We call LocalDate.now(zone).getMonth().getDisplayName(TextStyle.FULL, locale), for example with ZoneId.of(“UTC”) and Locale.US. The zone matters on the last evening of a month, when it is already the next month in UTC.

6.3. How do I format a date with the month name?

We use a pattern with MMMM for the full name or MMM for the abbreviation, such as DateTimeFormatter.ofPattern(“d MMMM uuuu”, Locale.US), which prints “5 March 2026”. More patterns are in formatting a date to a string.

6.4. Why does parsing a month name fail with “could not be parsed at index 0”?

Either the text does not fit the month names of the formatter’s locale or its case differs. Typical causes are “Sep” with Locale.UK, “MAR” with a case-sensitive formatter, and a missing locale, which uses the JVM default language.

7. Conclusion

The Month enum is the hub of every conversion. The method Month.of() turns a number into a constant, getDisplayName() turns the constant into a localized full, short or narrow name, and getValue() turns it back into a number.

For names coming in as text, a case-insensitive DateTimeFormatter with MMMM or MMM and the right locale parses full names and abbreviations in any language, whereas Month.valueOf() accepts only English constant names. We always pass the locale explicitly and watch out for “Sept” in British English. The Java date and time guide lists related conversions.

8. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.