TL; dr
Month.of( yourMonthNumber ) // Represent a month by its number, 1-12 for January-December. .getDisplayName( // Generate text of the name of the month automatically localized. TextStyle.SHORT_STANDALONE , // Specify how long or abbreviated the name of month should be. new Locale( "es" , "MX" ) // Locale determines (a) the human language used in translation, and (b) the cultural norms used in deciding issues of abbreviation, capitalization, punctuation, and so on. ) // Returns a String.
java.time.Month
It is much easier to do this in java.time classes, which supersede these problematic old legacy date and time classes.
The Month enumeration defines a dozen objects, one for each month.
Months from 1 to 12 for January-December.
Month month = Month.of( 2 ); // 2 → February.
Ask the object to generate a month name string automatically localized .
Configure TextStyle to indicate how long or short you want the name. Please note that in some languages (not English) the name of the month changes if used separately or as part of the full date. So every style of text has …_STANDALONE option.
Specify Locale to determine:
- What human language should be used in translation.
- What cultural norms should address issues such as abbreviation, punctuation and capitalization.
Example:
Locale l = new Locale( "es" , "MX" ); String output = Month.FEBRUARY.getDisplayName( TextStyle.SHORT_STANDALONE , l );
Name → Month Object
For your information, moving in the other direction (parsing the month name string to get the Month enumeration object) is not built-in. You can write your own class for this. Here is my quick attempt in this class. Use at your own risk. I have not thought about this code about any serious tests.
Using.
Month m = MonthDelocalizer.of( Locale.CANADA_FRENCH ).parse( "janvier" ) ; // Month.JANUARY
The code.
package com.basilbourque.example; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.time.Month; import java.time.format.TextStyle; import java.util.ArrayList; import java.util.List; import java.util.Locale; // For a given name of month in some language, determine the matching 'java.time.Month' enum object. // This class is the opposite of 'Month.getDisplayName' which generates a localized string for a given 'Month' object. // Usage… MonthDelocalizer.of( Locale.CANADA_FRENCH ).parse( "janvier" ) → Month.JANUARY // Assumes 'FormatStyle.FULL', for names without abbreviation. // About 'java.time.Month' enum: https://docs.oracle.com/javase/9/docs/api/java/time/Month.html // USE AT YOUR OWN RISK. Provided without guarantee or warranty. No serious testing or code review was performed. public class MonthDelocalizer { @NotNull private Locale locale; @NotNull private List < String > monthNames, monthNamesStandalone; // Some languages use an alternate spelling for a "standalone" month name used without the context of a date. // Constructor. Private, for static factory method. private MonthDelocalizer ( @NotNull Locale locale ) { this.locale = locale; // Populate the pair of arrays, each having the translated month names. int countMonthsInYear = 12; // Twelve months in the year. this.monthNames = new ArrayList <>( countMonthsInYear ); this.monthNamesStandalone = new ArrayList <>( countMonthsInYear ); for ( int i = 1 ; i <= countMonthsInYear ; i++ ) { this.monthNames.add( Month.of( i ).getDisplayName( TextStyle.FULL , this.locale ) ); this.monthNamesStandalone.add( Month.of( i ).getDisplayName( TextStyle.FULL_STANDALONE , this.locale ) ); } // System.out.println( this.monthNames ); // System.out.println( this.monthNamesStandalone ); } // Constructor. Private, for static factory method. // Personally, I think it unwise to default implicitly to a 'Locale'. But I included this in case you disagree with me, and to follow the lead of the *java.time* classes. --Basil Bourque private MonthDelocalizer ( ) { this( Locale.getDefault() ); } // static factory method, instead of constructors. // See article by Dr. Joshua Bloch. http://www.informit.com/articles/article.aspx?p=1216151 // The 'Locale' argument determines the human language and cultural norms used in de-localizing input strings. synchronized static public MonthDelocalizer of ( @NotNull Locale localeArg ) { MonthDelocalizer x = new MonthDelocalizer( localeArg ); // This class could be optimized by caching this object. return x; } // Attempt to translate the name of a month to look-up a matching 'Month' enum object. // Returns NULL if the passed String value is not found to be a valid name of month for the human language and cultural norms of the 'Locale' specified when constructing this parent object, 'MonthDelocalizer'. @Nullable public Month parse ( @NotNull String input ) { int index = this.monthNames.indexOf( input ); if ( - 1 == index ) { // If no hit in the contextual names, try the standalone names. index = this.monthNamesStandalone.indexOf( input ); } int ordinal = ( index + 1 ); Month m = ( ordinal > 0 ) ? Month.of( ordinal ) : null; // If we have a hit, determine the 'Month' enum object. Else return null. if ( null == m ) { throw new java.lang.IllegalArgumentException( "The passed month name: '" + input + " is not valid for locale: " + this.locale.toString() ); } return m; } // 'Object' class overrides. @Override public boolean equals ( Object o ) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; MonthDelocalizer that = ( MonthDelocalizer ) o; return locale.equals( that.locale ); } @Override public int hashCode ( ) { return locale.hashCode(); } public static void main ( String[] args ) { // Usage example: MonthDelocalizer monthDelocJapan = MonthDelocalizer.of( Locale.JAPAN ); try { Month m = monthDelocJapan.parse( "pink elephant" ); // Invalid input. } catch ( IllegalArgumentException e ) { // … handle error System.out.println( "ERROR: " + e.getLocalizedMessage() ); } // Ignore exception. (not recommended) if ( MonthDelocalizer.of( Locale.CANADA_FRENCH ).parse( "janvier" ).equals( Month.JANUARY ) ) { System.out.println( "GOOD - In locale "+Locale.CANADA_FRENCH+", the input 'janvier parses to Month.JANUARY." ); } } }
About java.time
The java.time framework is built into Java 8 and later. These classes supersede the nasty old obsolete date and time classes, such as java.util.Date , Calendar , and SimpleDateFormat .
The Joda-Time project, currently in maintenance mode , recommends switching to the java.time classes.
To learn more, see the Oracle Tutorial . And a search for many examples and explanations. JSR 310 specification .
You can exchange java.time objects directly with your database. Use a JDBC driver that conforms to JDBC 4.2 or later. No strings needed, no java.sql.* Needed.
Where to get java.time classes?
- Java SE 8 , Java SE 9 and later
- Built in.
- Part of the standard Java API with an embedded implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Most of the functionality of java.time has been ported to Java 6 and 7 in ThreeTen-Backport .
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier versions of Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP ....
The ThreeTen-Extra project extends java.time with additional classes. This project is a testing ground for possible future additions to java.time. Here you can find some useful classes such as Interval , YearWeek , YearQuarter and others .