¿Cómo puedo convertir un entero a un nombre de mes localizado en Java?

Obtengo un número entero y necesito convertir a los nombres de un mes en varios lugares:

Ejemplo para locale en-us:
1 -> enero
2 -> febrero

Ejemplo para locale es-mx:
1 -> Enero
2 -> Febrero

 import java.text.DateFormatSymbols; public String getMonth(int month) { return new DateFormatSymbols().getMonths()[month-1]; } 

Necesita usar LLLL para nombres de mes independientes. esto está documentado en la documentación de SimpleDateFormat , como por ejemplo:

 SimpleDateFormat dateFormat = new SimpleDateFormat( "LLLL", Locale.getDefault() ); dateFormat.format( date ); 

Yo usaría SimpleDateFormat. Alguien me corrige si hay una manera más fácil de hacer un calendario mensual, ahora hago esto en el código y no estoy tan seguro.

 import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; public String formatMonth(int month, Locale locale) { DateFormat formatter = new SimpleDateFormat("MMMM", locale); GregorianCalendar calendar = new GregorianCalendar(); calendar.set(Calendar.DAY_OF_MONTH, 1); calendar.set(Calendar.MONTH, month-1); return formatter.format(calendar.getTime()); } 

Así es como lo haría. Dejaré la comprobación de rango en el int month hasta usted.

 import java.text.DateFormatSymbols; public String formatMonth(int month, Locale locale) { DateFormatSymbols symbols = new DateFormatSymbols(locale); String[] monthNames = symbols.getMonths(); return monthNames[month - 1]; } 

Usando SimpleDateFormat.

 import java.text.SimpleDateFormat; public String formatMonth(String month) { SimpleDateFormat monthParse = new SimpleDateFormat("MM"); SimpleDateFormat monthDisplay = new SimpleDateFormat("MMMM"); return monthDisplay.format(monthParse.parse(month)); } formatMonth("2"); 

Resultado: febrero

Aparentemente en Android 2.2 hay un error con SimpleDateFormat.

Para usar los nombres de los meses, debe definirlos usted mismo en sus recursos:

  January February March April May June July August September October November December  

Y luego utilícelos en su código así:

 /** * Get the month name of a Date. eg January for the Date 2011-01-01 * * @param date * @return eg "January" */ public static String getMonthName(Context context, Date date) { /* * Android 2.2 has a bug in SimpleDateFormat. Can't use "MMMM" for * getting the Month name for the given Locale. Thus relying on own * values from string resources */ String result = ""; Calendar cal = Calendar.getInstance(); cal.setTime(date); int month = cal.get(Calendar.MONTH); try { result = context.getResources().getStringArray(R.array.month_names)[month]; } catch (ArrayIndexOutOfBoundsException e) { result = Integer.toString(month); } return result; } 

java.time

Desde Java 1.8 (o 1.7 y 1.6 con ThreeTen-Backport ) puede usar esto:

 Month.of(integerMonth).getDisplayName(TextStyle.FULL_STANDALONE, locale); 

Tenga en cuenta que integerMonth está basado en 1, es decir, 1 es para enero. El rango siempre es de 1 a 12 para enero-diciembre (es decir, solo para el calendario gregoriano).

tl; dr

 Month.of( yourMonthNumber ) .getDisplayName( TextStyle.SHORT_STANDALONE , new Locale( "es" , "MX" ) ) 

java.time.Month

Mucho más fácil de hacer ahora en las clases de java.time que suplantan a estas problemáticas antiguas clases heredadas de fecha y hora.

La enumeración de Month define una docena de objetos, uno por cada mes.

Los meses están numerados del 1 al 12 para enero-diciembre.

 Month month = Month.of( 2 ); // 2 → February. 

Pídale al objeto que genere una Cadena del nombre del mes, automáticamente localizado .

Ajuste el TextStyle para especificar por cuánto tiempo o abreviar quiere el nombre. Tenga en cuenta que en algunos idiomas (no en inglés) el nombre del mes varía si se usa solo o como parte de una fecha completa. Por lo tanto, cada estilo de texto tiene una …_STANDALONE variante.

Especifique una Locale para determinar:

  • ¿Qué lenguaje humano debería usarse en la traducción?
  • Qué normas culturales deberían decidir cuestiones tales como abreviatura, puntuación y capitalización.

Ejemplo:

 Locale l = new Locale( "es" , "MX" ); String output = Month.FEBRUARY.getDisplayName( TextStyle.SHORT_STANDALONE , l ); // Or Locale.US, Locale.CANADA_FRENCH. 

Nombre → objeto Month

FYI, ir en la otra dirección (analizar una cadena de nombre del mes para obtener un objeto Enum del Month ) no está incorporado. Podrías escribir tu propia clase para hacerlo. Aquí está mi bash rápido en tal clase. Use bajo su propio riesgo . No pensé seriamente en este código ni en ninguna prueba seria.

Uso.

 Month m = MonthDelocalizer.of( Locale.CANADA_FRENCH ).parse( "janvier" ) ; // Month.JANUARY 

Código.

 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." ); } } } 

Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las problemáticas antiguas clases heredadas de fecha y hora como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Use un controlador JDBC que cumpla con JDBC 4.2 o posterior. Sin necesidad de cadenas, sin necesidad de clases java.sql.* .

¿Dónde obtener las clases de java.time?

  • Java SE 8 , Java SE 9 y posterior
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de las implementaciones del paquete de Android de las clases java.time.
    • Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Consulte Cómo utilizar ThreeTenABP ….

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .

Existe un problema cuando utiliza la clase DateFormatSymbols para su método getMonthName para obtener Month by Name que muestra Month by Number en algunos dispositivos Android. He resuelto este problema haciendo esto:

En String_array.xml

  January February March April May June July August September October November December  

En la clase Java simplemente llame a esta matriz de esta manera:

 public String[] getYearMonthName() { return getResources().getStringArray(R.array.year_month_names); //or like //return cntx.getResources().getStringArray(R.array.month_names); } String[] months = getYearMonthName(); if (i < months.length) { monthShow.setMonthName(months[i] + " " + year); } 

Happy Coding 🙂

  public static void main(String[] args) { SimpleDateFormat format = new SimpleDateFormat("MMMMM", new Locale("en", "US")); System.out.println(format.format(new Date())); }