Cómo analizar el nombre de un mes (cadena) en un entero para comparar en C #?

Necesito poder comparar algunos nombres de mes que tengo en una matriz.

Sería bueno si hubiera alguna manera directa como:

Month.toInt("January") > Month.toInt("May") 

Mi búsqueda en Google parece sugerir que la única manera es escribir su propio método, pero parece ser un problema bastante común que creo que ya se hubiera implementado en .Net. ¿Alguien hizo esto antes?

DateTime.ParseExact(monthName, "MMMM", CultureInfo.CurrentCulture ).Month

Aunque, para sus propósitos, probablemente sea mejor que simplemente cree un Dictionary asignando el nombre del mes a su valor.

Podrías hacer algo como esto:

 Convert.ToDate(month + " 01, 1900").Month 

Si usa el método DateTime.ParseExact() que varias personas han sugerido, debe considerar cuidadosamente lo que quiere que suceda cuando la aplicación se ejecute en un entorno que no sea inglés.

En Dinamarca, ¿cuál de ParseExact("Januar", ...) y ParseExact("January", ...) deberían funcionar y cuáles deberían fallar?

Esa será la diferencia entre CultureInfo.CurrentCulture y CultureInfo.InvariantCulture .

Puede usar el método DateTime.Parse para obtener un objeto DateTime y luego verificar su propiedad Month. Haz algo como esto:

 int month = DateTime.Parse("1." + monthName + " 2008").Month; 

El truco es construir una fecha válida para crear un objeto DateTime.

Puedes usar una enumeración de meses:

 public enum Month { January, February, // (...) December, } public Month ToInt(Month Input) { return (int)Enum.Parse(typeof(Month), Input, true)); } 

Sin embargo, no estoy 100% seguro de la syntax para enum.Parse ().

No es necesario crear una instancia de DateTime para hacer esto. Es tan simple como esto:

 public static class Month { public static int ToInt(this string month) { return Array.IndexOf( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames, month.ToLower(CultureInfo.CurrentCulture)) + 1; } } 

Me estoy ejecutando en la cultura da-DK , por lo que esta prueba de unidad pasa:

 [Theory] [InlineData("Januar", 1)] [InlineData("Februar", 2)] [InlineData("Marts", 3)] [InlineData("April", 4)] [InlineData("Maj", 5)] [InlineData("Juni", 6)] [InlineData("Juli", 7)] [InlineData("August", 8)] [InlineData("September", 9)] [InlineData("Oktober", 10)] [InlineData("November", 11)] [InlineData("December", 12)] public void Test(string monthName, int expected) { var actual = monthName.ToInt(); Assert.Equal(expected, actual); } 

Lo dejaré como ejercicio para que el lector cree una sobrecarga donde pueda pasar un CultureInfo explícito.

Una solución simple sería crear un diccionario con nombres y valores. Luego, usando Contiene () puedes encontrar el valor correcto.

 Dictionary months = new Dictionary() { { "january", "01"}, { "february", "02"}, { "march", "03"}, { "april", "04"}, { "may", "05"}, { "june", "06"}, { "july", "07"}, { "august", "08"}, { "september", "09"}, { "october", "10"}, { "november", "11"}, { "december", "12"}, }; foreach (var month in months) { if (StringThatContainsMonth.ToLower().Contains(month.Key)) { string thisMonth = month.Value; } } 

Si está utilizando c # 3.0 (o superior) puede usar extensores

Lo traduzco al código C # en la versión en español, respecto a:

 public string ObtenerNumeroMes(string NombreMes){ string NumeroMes; switch(NombreMes) { case ("ENERO") : NumeroMes = "01"; return NumeroMes; case ("FEBRERO") : NumeroMes = "02"; return NumeroMes; case ("MARZO") : NumeroMes = "03"; return NumeroMes; case ("ABRIL") : NumeroMes = "04"; return NumeroMes; case ("MAYO") : NumeroMes = "05"; return NumeroMes; case ("JUNIO") : NumeroMes = "06"; return NumeroMes; case ("JULIO") : NumeroMes = "07"; return NumeroMes; case ("AGOSTO") : NumeroMes = "08"; return NumeroMes; case ("SEPTIEMBRE") : NumeroMes = "09"; return NumeroMes; case ("OCTUBRE") : NumeroMes = "10"; return NumeroMes; case ("NOVIEMBRE") : NumeroMes = "11"; return NumeroMes; case ("DICIEMBRE") : NumeroMes = "12"; return NumeroMes; default: Console.WriteLine("Error"); return "ERROR"; } } 

Y respondiendo esto siete años después de que se hizo la pregunta, es posible hacer esta comparación usando métodos integrados:

 Month.toInt("January") > Month.toInt("May") 

se convierte

 Array.FindIndex( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames, t => t.Equals("January", StringComparison.CurrentCultureIgnoreCase)) > Array.FindIndex( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames, t => t.Equals("May", StringComparison.CurrentCultureIgnoreCase)) 

Que se pueden refactorizar en un método de extensión para simplificar. El siguiente es un ejemplo LINQPad (de ahí el llamado al método Dump() ):

 void Main() { ("January".GetMonthIndex() > "May".GetMonthIndex()).Dump(); ("January".GetMonthIndex() == "january".GetMonthIndex()).Dump(); ("January".GetMonthIndex() < "May".GetMonthIndex()).Dump(); } public static class Extension { public static int GetMonthIndex(this string month) { return Array.FindIndex( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames, t => t.Equals(month, StringComparison.CurrentCultureIgnoreCase)); } } 

Con salida:

 False True True 
 Public Function returnMonthNumber(ByVal monthName As String) As Integer Select Case monthName.ToLower Case Is = "january" Return 1 Case Is = "february" Return 2 Case Is = "march" Return 3 Case Is = "april" Return 4 Case Is = "may" Return 5 Case Is = "june" Return 6 Case Is = "july" Return 7 Case Is = "august" Return 8 Case Is = "september" Return 9 Case Is = "october" Return 10 Case Is = "november" Return 11 Case Is = "december" Return 12 Case Else Return 0 End Select End Function 

el código de precaución está en la versión Beta.

Lo que hice fue utilizar SimpleDateFormat para crear una cadena de formato, analizar el texto en una fecha y luego recuperar el mes a partir de eso. El código está abajo:

 int year = 2012 \\or any other year String monthName = "January" \\or any other month SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yyyy"); int monthNumber = format.parse("01-" + monthName + "-" + year).getMonth();