Bagaimana cara mengurai nama bulan (string) menjadi integer untuk perbandingan di C #?

92

Saya harus dapat membandingkan beberapa nama bulan yang saya miliki dalam sebuah array.

Alangkah baiknya jika ada beberapa cara langsung seperti:

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

Pencarian Google saya tampaknya menyarankan satu-satunya cara adalah menulis metode Anda sendiri, tetapi ini sepertinya masalah yang cukup umum sehingga saya pikir itu akan sudah diterapkan di .Net, ada yang melakukan ini sebelumnya?

tumpahan
sumber

Jawaban:

174

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

Meskipun, untuk tujuan Anda, Anda mungkin lebih baik hanya membuat Dictionary<string, int>pemetaan nama bulan ke nilainya.

James Curran
sumber
11
Pastikan untuk mempertimbangkan stackoverflow.com/questions/258793/… saat memutuskan apakah akan menggunakan CultureInfo.CurrentCulture atau CultureInfo.InvariantCulture
Rasmus Faber
20

Anda bisa melakukan sesuatu seperti ini:

Convert.ToDate(month + " 01, 1900").Month
Aaron Palmer
sumber
19

Jika Anda menggunakan DateTime.ParseExact()-metode yang disarankan beberapa orang, Anda harus mempertimbangkan dengan cermat apa yang Anda inginkan terjadi ketika aplikasi berjalan di lingkungan non-Inggris!

Di Denmark, mana dari ParseExact("Januar", ...)dan ParseExact("January", ...)harus berhasil dan mana yang harus gagal?

Itulah perbedaan antara CultureInfo.CurrentCulturedan CultureInfo.InvariantCulture.

Rasmus Faber
sumber
10

Salah satu solusi sederhana adalah membuat Kamus dengan nama dan nilai. Kemudian menggunakan Contains () Anda dapat menemukan nilai yang tepat.

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;
    }
}
Carlos A. Ortiz
sumber
9

Anda dapat menggunakan metode DateTime.Parse untuk mendapatkan objek DateTime lalu memeriksa properti Bulannya. Lakukan sesuatu seperti ini:

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

Triknya adalah membuat tanggal yang valid untuk membuat objek DateTime.

Rune Grimstad
sumber
9

Anda dapat menggunakan enum bulan:

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

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

Saya tidak 100% yakin tentang sintaks untuk enum.Parse (), meskipun.

Treb
sumber
1
Ini harus "public Month ToInt (string Input) {...}" tapi sebaliknya itu benar.
James Curran
1
Saya tahu ini adalah komentar lama tetapi saya pikir saya akan menunjukkan Anda harus memulai enum Anda dari 1, misalnya public enum Month { January = 1, Feburary }dan juga melemparkan ke int, bukan Bulan.
eth0
@ eth0: Ups ... Anda benar. Diperbaiki, terima kasih telah menunjukkannya ;-)
Treb
7

Anda tidak perlu membuat instance DateTime untuk melakukan ini. Sesederhana ini:

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

Saya menjalankan da-DKbudaya, jadi tes unit ini lolos:

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

Saya akan menyerahkannya sebagai latihan kepada pembaca untuk membuat kelebihan beban di mana Anda bisa meneruskan CultureInfo eksplisit.

Mark Seemann
sumber
Penggunaan yang bagus ToLower()- Saya tidak menyadari salah satu kelebihan mengonversi string using the casing rules of the specified culturemeskipun agar adil tidak jelas dari nama metode bahwa ia mungkin menyediakan fungsionalitas itu.
David Clarke
1
Ok, jadi saya telah menguji ini menggunakan LINQPad dan saya tidak bisa membuatnya berfungsi di saya CurrentCulture. Keduanya "January".ToLower(CultureInfo.CurrentCulture).Dump();dan "January".ToLower(new CultureInfo("en-NZ")).Dump();keluaran januarytetapi nama bulan dikapitalisasi dalam CurrentCulture.DateTimeFormat.MonthNames.
David Clarke
1
@DavidClarke Well, ya, Anda sedang memanggil fungsi disebut ToLower:) Sebenarnya, ada cacat logis sedikit dalam kode saya, karena nama-nama bulan yang diberikan karena semua huruf kecil di da-DK. Jadi, salah satu tidak boleh huruf kecil masukan, atau yang lain juga harus huruf kecil semua nama bulan - tergantung pada apakah kecocokan tidak peka huruf besar / kecil diinginkan atau tidak.
Mark Seemann
1
Ya, saya menafsirkan dokumentasi yang using the casing rules of the specified cultureberarti bahwa itu akan menggunakan huruf besar misalnya bulan dan hari per CultureInfo. Yang berfungsi dalam contoh Anda karena nama bulan menggunakan huruf kecil. Demonstrasi yang efektif menggunakan pengujian unit untuk menyesatkan. Mungkin layak untuk diedit untuk memperjelas bahwa contoh Anda adalah kasus tepi :-)
David Clarke
2

Dan menjawab ini tujuh tahun setelah pertanyaan diajukan, adalah mungkin untuk melakukan perbandingan ini menggunakan metode bawaan:

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

menjadi

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

Yang dapat direfraktorisasi menjadi metode ekstensi untuk kesederhanaan. Berikut ini adalah contoh LINQPad (karenanya Dump()metode memanggil):

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

Dengan keluaran:

False
True
True
David Clarke
sumber
Ini adalah solusi yang jauh lebih baik menggunakan perbandingan string IgnoreCase. Ini berfungsi dengan baik untuk pertanyaan OP, namun jika Anda ingin menggunakan metode ini untuk mengonversi ke nilai yang sama yang dikembalikan oleh DateTime.Month, saya sarankan menambahkan +1 pada hasilnya. Persyaratan perbandingan OP masih memuaskan atau tentu saja.
iGanja
1

Jika Anda menggunakan c # 3.0 (atau lebih tinggi), Anda dapat menggunakan extender

Adam Naylor
sumber
Kalau begitu ya, sayangnya saya pikir metode Anda sendiri akan menjadi solusi paling elegan.
Adam Naylor
@AdamNaylor: apa itu extender? dapatkah Anda menjelaskan jawaban Anda dengan sebuah contoh?
Amir
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

kode hati-hati dalam versi Beta.

Thabiso
sumber
Jawaban yang diterima jauh lebih baik.
James A Mohler
1

Saya menerjemahkannya ke dalam kode C # dalam versi bahasa Spanyol, salam:

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

        }

   }
Maria Carolina Araujo
sumber
0

Apa yang saya lakukan adalah menggunakan SimpleDateFormat untuk membuat string format, dan mengurai teks menjadi tanggal, lalu mengambil bulan dari itu. Kode di bawah ini:

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();
Ebenezer Ampiah
sumber
0

Kode ini membantu Anda ...

using System.Globalization;

....

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

Metode GetMonthName - mengembalikan string ...

Jika Anda ingin mendapatkan bulan sebagai bilangan bulat, cukup gunakan -

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

Saya harap, ini membantu Anda !!!

Terima kasih!!!

Nitika Chopra
sumber