Как разобрать название месяца (строку) в целое число для сравнения в C #? - PullRequest
88 голосов
/ 03 ноября 2008

Мне нужно иметь возможность сравнивать названия некоторых месяцев в массиве.

Было бы неплохо, если бы был какой-то прямой путь:

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

Похоже, что мой поиск в Google предлагает единственный способ - написать свой собственный метод, но это кажется достаточно распространенной проблемой, и я думаю, что это уже было реализовано в .Net, кто-нибудь делал это раньше?

Ответы [ 12 ]

164 голосов
/ 03 ноября 2008

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

Хотя для ваших целей вам, вероятно, будет лучше просто создать Dictionary<string, int>, отображающий название месяца и его значение.

20 голосов
/ 03 ноября 2008

Вы можете сделать что-то вроде этого:

Convert.ToDate(month + " 01, 1900").Month
19 голосов
/ 03 ноября 2008

Если вы используете DateTime.ParseExact() -метод, предложенный несколькими людьми, вы должны тщательно продумать, что вы хотите, чтобы происходило, когда приложение работает в неанглийской среде!

В Дании, какие из ParseExact("Januar", ...) и ParseExact("January", ...) должны работать, а какие - нет?

Это будет разница между CultureInfo.CurrentCulture и CultureInfo.InvariantCulture.

8 голосов
/ 03 ноября 2008

Вы можете использовать метод DateTime.Parse, чтобы получить объект DateTime, а затем проверить его свойство Month. Сделайте что-то вроде этого:

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

Хитрость в том, чтобы создать действительную дату для создания объекта DateTime.

7 голосов
/ 07 мая 2015

Одним из простых решений было бы создание словаря с именами и значениями. Затем с помощью Contains () вы можете найти правильное значение.

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;
    }
}
7 голосов
/ 23 сентября 2012

Вам не нужно создавать экземпляр DateTime для этого. Это так просто:

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

Я работаю на культуре da-DK, поэтому этот юнит-тест проходит:

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

Я оставлю это в качестве упражнения для читателя, чтобы создать перегрузку, где вы можете передать явное CultureInfo.

7 голосов
/ 03 ноября 2008

Вы можете использовать перечисление месяцев:

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

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

Я не уверен на 100% в синтаксисе enum.Parse (), хотя.

2 голосов
/ 11 июня 2015

И, отвечая на эти семь лет после того, как вопрос был задан, можно сделать это сравнение, используя встроенные методы:

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

становится

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

Что может быть преобразовано в метод расширения для простоты. Ниже приведен пример LINQPad (следовательно, вызовы метода 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));
    }
}

С выводом:

False
True
True
1 голос
/ 23 апреля 2013

Я перевожу его на C # код в испанской версии, с уважением:

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

        }

   }
1 голос
/ 03 ноября 2008

Если вы используете c # 3.0 (или выше), вы можете использовать экстендеры

...