2008-11-03 9 views
84

Necesito poder comparar algunos nombres de mes que tengo en una matriz.¿Cómo se analiza el nombre de un mes (cadena) en un entero para su comparación en C#?

Sería agradable si había alguna manera directa como:

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

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

Respuesta

142

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

Aunque, para sus propósitos, es probable que sea mejor simplemente creando un Dictionary<string, int> mapear el nombre del mes a su valor

+11

Asegúrese de considerar http://stackoverflow.com/questions/258793/how-to-parse-a-month-name-string-to-an-integer-for-comparison-in-c#258895 cuando decida si desea use CultureInfo.CurrentCulture o CultureInfo.InvariantCulture –

1

Si está usando C# 3.0 (o superior) se puede utilizar extensores

+0

estoy usando .NET 2.0 – spilliton

+0

Entonces sí, por desgracia, creo que su propio método sería el la solución más elegante. –

18

se podría hacer algo como esto:

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

Usted puede utilizar el método DateTime.Parse para obtener un objeto DateTime y después comprobar su propiedad mes. Haga algo como esto:

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

El truco consiste en crear una fecha válida para crear un objeto DateTime.

7

usted puede utilizar una enumeración de meses:

public enum Month 
{ 
    January, 
    February, 
    // (...) 
    December, 
}  

public Month ToInt(Month Input) 
{ 
    return (int)Enum.Parse(typeof(Month), Input, true)); 
} 

no estoy 100% seguro de la sintaxis para enum.Parse(), sin embargo.

+1

Necesitaría ser "public Month ToInt (string Input) {...}" pero de lo contrario es correcto. –

+1

Sé que este es un comentario antiguo, pero pensé que debería señalar que debe comenzar su enum desde 1, p. 'public enum Month {January = 1, Feburary}' y también lanzado a int en lugar de Month. – eth0

+0

@ eth0: Oops ... tienes razón. Lo corrigió, gracias por señalarlo ;-) – Treb

18

Si utiliza el método DateTime.ParseExact() que muchas 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ía funcionar y cuál debería fallar?

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

0
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 

código de precaución en la versión Beta.

+0

La respuesta aceptada es mucho mejor. –

0

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

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

Este código no es C#. Es Java. – Indian

5

No es necesario crear una instancia de DateTime para hacerlo. 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; 
    } 
} 

estoy corriendo en la cultura da-DK, por lo que esta prueba de la 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 dejo como ejercicio para el lector para crear una sobrecarga donde puedes pasar un CultureInfo explícito.

+0

Buen uso de 'ToLower()' - No sabía que una de las sobrecargas convierte la cadena 'usando las reglas de la cultura especificada 'aunque, para ser justos, no es obvio por el nombre del método que pueda permitirse esa funcionalidad. –

+0

Ok, así que he estado probando esto usando LINQPad y no puedo hacer que funcione en mi 'CurrentCulture'. Ambos '" Enero ".ToLower (CultureInfo.CurrentCulture) .Dump();' y '" January ".ToLower (nuevo CultureInfo (" en-NZ ")). Dump();' output 'january' pero los nombres de los meses son capitalizado en 'CurrentCulture.DateTimeFormat.MonthNames'. –

+1

@DavidClarke Bueno, sí, * estás * llamando a una función llamada 'ToLower' :) En realidad, hay un pequeño error lógico en mi código, ya que los nombres de los meses * se dan como minúsculas en da-DK. Por lo tanto, uno no debe minúsculas en la entrada, o bien uno también debe minúsculas en todos los nombres de los meses, dependiendo de si desea o no una coincidencia que no distinga entre mayúsculas y minúsculas. –

1

traduzco en código C# en la versión española, se refiere 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"; 

     } 

    } 
5

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

Dictionary<string, string> months = new Dictionary<string, string>() 
{ 
       { "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; 
    } 
} 
1

Y respondiendo a estos siete años después de que se hizo la pregunta, es posible hacer esta comparación mediante los métodos incorporados en:

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

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

Cuál puede ser readaptado en un método de extensión para simplificar. El siguiente es un ejemplo LINQPad (de ahí las llamadas Dump() método):

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 
Cuestiones relacionadas