Como analisar um nome de mês (string) para um número inteiro para comparação em c #?

Eu preciso ser capaz de comparar alguns nomes de mês que tenho em uma matriz.

Seria legal se houvesse alguma maneira direta como:

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

Minha busca no Google parece sugerir que a única maneira é escrever seu próprio método, mas isso parece um problema bastante comum que eu pensaria que já teria sido implementado em .Net, alguém fez isso antes?

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

Embora, para seus propósitos, você provavelmente será melhor apenas criar um Dictionary mapeando o nome do mês para seu valor.

Você poderia fazer algo assim:

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

Se você usar o método DateTime.ParseExact() que várias pessoas sugeriram, você deve considerar cuidadosamente o que deseja que aconteça quando o aplicativo for executado em um ambiente que não esteja em inglês.

Na Dinamarca, quais de ParseExact("Januar", ...) e ParseExact("January", ...) devem funcionar e quais devem falhar?

Essa será a diferença entre CultureInfo.CurrentCulture e CultureInfo.InvariantCulture .

Você pode usar o método DateTime.Parse para obter um object DateTime e, em seguida, verificar sua propriedade Month. Faça algo assim:

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

O truque é criar uma data válida para criar um object DateTime.

Você pode usar um enum de meses:

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

Eu não estou 100% certo sobre a syntax para enum.Parse (), no entanto.

Você não precisa criar uma instância de DateTime para fazer isso. É tão simples assim:

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

Eu estou correndo na cultura da-DK , então este teste de unidade passa:

 [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); } 

Deixarei como um exercício para o leitor criar uma sobrecarga onde você pode passar um CultureInfo explícito.

Uma solução simples seria criar um dictionary com nomes e valores. Em seguida, usando Contains () você pode encontrar o valor correto.

 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; } } 

Se você estiver usando c # 3.0 (ou acima), você pode usar extensores

Eu traduzi-o em código C # na versão em espanhol, respeita:

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

E respondendo a isso sete anos após a pergunta ser feita, é possível fazer essa comparação usando methods internos:

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

torna-se

 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 pode ser refatorado em um método de extensão para simplificar. O seguinte é um exemplo do LINQPad (daí as chamadas do 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)); } } 

Com saída:

 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 

O código de precaução está na versão Beta.

O que eu fiz foi usar SimpleDateFormat para criar uma string de formato e analisar o texto para uma data e, em seguida, recuperar o mês a partir disso. O código está abaixo:

 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();