C#で比較するために月の名前(文字列)を整数に解析する方法は?


92

配列にあるいくつかの月の名前を比較できるようにする必要があります。

次のような直接的な方法があればいいでしょう:

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

私のグーグル検索はあなた自身の方法を書くことが唯一の方法を提案しているようですが、これはそれがすでに.Netに実装されているだろうと思う一般的な十分な問題のようです、これは以前にこれをやった人ですか?

回答:


174

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

ただし、目的のためにDictionary<string, int>、月の名前とその値のマッピングを作成する方がよいでしょう。


11
CultureInfo.CurrentCultureまたはCultureInfo.InvariantCultureを使用するかどうかを決定するときは、必ずstackoverflow.com/questions/258793/…を検討してください
Rasmus Faber


19

DateTime.ParseExact()複数の人が提案した-method を使用する場合は、アプリケーションが英語以外の環境で実行されたときに何が発生するかを慎重に検討する必要があります。

デンマークでは、のどParseExact("Januar", ...)ParseExact("January", ...)動作するはずですし、これに失敗する必要がありますか?

それがとの違いにCultureInfo.CurrentCultureなりCultureInfo.InvariantCultureます。


10

簡単な解決策の1つは、名前と値を含む辞書を作成することです。次に、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 }Monthではなくintにキャストする必要があることを指摘したいと思います。
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()-オーバーロードの1つが文字列を変換することに気づいていませんでしusing the casing rules of the specified cultureたが、公平を期すために、メソッド名からその機能を提供できるかどうかは明らかではありません。
David Clarke

1
わかりました、それで私はLINQPadを使用してこれをテストしており、それを私ので動作させることはできませんCurrentCulture"January".ToLower(CultureInfo.CurrentCulture).Dump();および"January".ToLower(new CultureInfo("en-NZ")).Dump();出力の両方ですjanuaryが、月の名前はで大文字になっていCurrentCulture.DateTimeFormat.MonthNamesます。
デビッドクラーク2015年

1
@DavidClarkeええ、そうです。あなたToLower :) という関数呼び出しています。実際には、da-DK では月の名前すべて小文字で指定されているため、コードに若干の論理的な欠陥があります。したがって、大文字と小文字を区別しない一致が必要かどうかに応じて、入力を小文字にしないか、月の名前もすべて小文字にする必要があります。
Mark Seemann、2015年

1
はい、私はusing the casing rules of the specified cultureそれが例えば毎月と日を大文字にするという意味でドキュメントを解釈していましたCultureInfo。これは、月の名前が小文字であるため、例では機能します。誤解を招くユニットテストの効果的なデモンストレーション。あなたの例がエッジケースであることを明確にするために編集に値するかもしれません:-)
David Clarke

2

そして、質問が出されてから7年後に答えると、組み込みのメソッドを使用してこの比較を行うことができます。

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 2018

1

C#3.0(またはそれ以上)を使用している場合は、エクステンダーを使用できます


それからうん、残念ながら私はあなた自身の方法が最もエレガントな解決策になると思います。
Adam Naylor

@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

注意コードはベータ版です。


受け入れられた答えははるかに優れています。
James A Mohler

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;

よろしくお願いします。

ありがとう!!!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.