如何将月份名称(字符串)解析为整数以在C#中进行比较?


92

我需要能够比较数组中的某些月份名称。

如果有一些直接的方法,那就太好了:

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

我的Google搜索似乎表明唯一的方法是编写自己的方法,但这似乎是一个足够普遍的问题,我认为它已经在.Net中实现,以前有人这样做过吗?

Answers:


174

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

尽管就您的目的而言,最好只创建一个Dictionary<string, int>月份名称到其值的映射。


11
在决定是否使用CultureInfo.CurrentCulture或CultureInfo.InvariantCulture
Rasmus Faber


19

如果使用DateTime.ParseExact()几个人建议的-方法,则应仔细考虑当应用程序在非英语环境中运行时想要发生的事情!

在丹麦,哪个ParseExact("Januar", ...)ParseExact("January", ...)应该工作,哪个应该失败?

这将是之间的差异CultureInfo.CurrentCultureCultureInfo.InvariantCulture


10

一种简单的解决方案是使用名称和值创建一个Dictionary。然后使用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;
    }
}

9

您可以使用DateTime.Parse方法获取DateTime对象,然后检查其Month属性。做这样的事情:

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

技巧是建立一个有效的日期来创建DateTime对象。


9

您可以使用一个月的枚举:

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

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

我对enum.Parse()的语法不确定100%。


1
它必须是“ public Month ToInt(string Input){...}”,否则是正确的。
James Curran

1
我知道这是一个古老的评论,但我想指出您应该从1开始枚举,public enum Month { January = 1, Feburary }并且还应强制转换为int而不是Month。
eth0

@ eth0:糟糕...您是对的。更正了它,谢谢您指出;-)
Treb

7

您无需创建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。


很好的使用ToLower()-我不知道其中一个重载会转换字符串,using the casing rules of the specified culture尽管公平地说,从方法名称中并不能明显看出它可以提供该功能。
大卫·克拉克

1
好的,所以我一直在使用LINQPad对此进行测试,但是我无法在LINQPad中使用它CurrentCulture。无论"January".ToLower(CultureInfo.CurrentCulture).Dump();"January".ToLower(new CultureInfo("en-NZ")).Dump();输出january,但一个月名都是大写的CurrentCulture.DateTimeFormat.MonthNames
大卫·克拉克

1
@DavidClarke嗯,是的,你呼叫被叫功能ToLower:)其实,有一个在我的代码稍有逻辑的漏洞,因为一个月的名称赋予作为DA-DK全部小写。因此,要么不应该小写输入,要么应该也将所有月份名称都小写-取决于是否需要不区分大小写的匹配。
Mark Seemann 2015年

1
是的,我解释文档using the casing rules of the specified culture的意思是它将大写,例如每个月数月日CultureInfo。在您的示例中有效,因为月份名称是小写字母。有效演示使用单元测试进行误导。可能值得进行修改,以使您的示例清晰易懂:-)
David Clarke 2015年

2

在问了问题七年后回答了这个问题,可以使用内置方法进行此比较:

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

使用IgnoreCase字符串比较,这是一个更好的解决方案。这对于OP的问题很好用,但是,如果要使用此方法转换为DateTime.Month返回的相同值,建议将+1添加到结果中。OP的比较要求还是很满意。
iGanja

1

如果您使用的是c#3.0(或更高版本),则可以使用扩展程序


然后,是的,不幸的是,我认为您自己的方法将是最优雅的解决方案。
亚当·内罗尔

@AdamNaylor:什么是扩展剂?您可以举例说明您的答案吗?
阿米尔

1
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

警告代码为Beta版本。


接受的答案要好得多。
詹姆斯·阿·莫勒

1

我将其翻译成西班牙语版本的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";

        }

   }

0

我所做的是使用SimpleDateFormat创建格式字符串,然后将文本解析为日期,然后从中检索月份。代码如下:

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

0

此代码可以帮助您...

using System.Globalization;

....

string FullMonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(DateTime.UtcNow.Month);

GetMonthName方法-返回字符串...

如果要以整数形式表示月份,则只需使用-

DateTime dt= DateTime.UtcNow;
int month= dt.Month;

希望对您有帮助!!!

谢谢!!!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.