¿Cómo analizar el nombre de un mes (cadena) en un número entero para compararlo en C#?

StackOverflow https://stackoverflow.com/questions/258793

  •  06-07-2019
  •  | 
  •  

Pregunta

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

Sería bueno si hubiera alguna forma 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 esto parece un problema bastante común que creo que ya se habría implementado en .Net. ¿Alguien ha hecho esto antes?

¿Fue útil?

Solución

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

Aunque, para sus propósitos, probablemente sea mejor crear una Dictionary<string, int> asignación del nombre del mes a su valor.

Otros consejos

Podrías hacer algo como esto:

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

Si usas el DateTime.ParseExact()-Método que varias personas han sugerido, ¡debes considerar cuidadosamente lo que quieres que suceda cuando la aplicación se ejecute en un entorno que no esté en 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.

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

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

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

Puede 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 sintaxis de enum.Parse ().

No tiene que 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 un ejercicio para el lector para crear una sobrecarga en la que pueda pasar un CultureInfo explícito.

Una solución sencilla sería crear un Diccionario con nombres y valores. Luego, utilizando Contains () puede 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;
    }
}

Y respondiendo esto siete años después de que se hizo la pregunta, es posible hacer esta comparación utilizando 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 puede refactorizar en un método de extensión para simplificar. El siguiente es un ejemplo de LINQPad (de ahí las Dump() llamadas al 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

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

Lo traduzco al código C # en la versión española, saludos:

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

        }

   }
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 versión Beta.

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

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();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top