C # ile karşılaştırma yapmak için ay adını (dize) bir tam sayıya nasıl ayrıştırabilirim?


94

Bir dizide sahip olduğum bazı ay adlarını karşılaştırabilmem gerekiyor.

Şunun gibi doğrudan bir yol olsaydı iyi olurdu:

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

Google aramam tek yolun kendi yönteminizi yazmak olduğunu gösteriyor gibi görünüyor, ancak bu zaten .Net'te uygulanmış olacağını düşündüğüm kadar yaygın bir sorun gibi görünüyor, bunu daha önce yapan var mı?

Yanıtlar:


177

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

Yine de, amaçlarınız için, Dictionary<string, int>ayın adını değeriyle eşleştirerek muhtemelen daha iyi olacaksınız .


11
Değerlendirmeyi unutmayın stackoverflow.com/questions/258793/... CultureInfo.CurrentCulture veya CultureInfo.InvariantCulture kullanmaya karar verirken
Rasmus Faber

20

Bunun gibi bir şey yapabilirsiniz:

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

19

Eğer kullanırsanız DateTime.ParseExact()birkaç kişi bebeklikte görülen kullanılan yöntem, dikkatli ne olmasını istediğinizi düşünmelisiniz zaman İngilizce olmayan bir ortamda uygulamasının çalıştığı!

In Danimarka, hangisinin ParseExact("Januar", ...)ve ParseExact("January", ...)çalışması gerekir ve hangi başarısız gerekir?

Yani arasındaki fark olacaktır CultureInfo.CurrentCultureve CultureInfo.InvariantCulture.


10

Basit bir çözüm, isimler ve değerler içeren bir Sözlük oluşturmaktır. Ardından İçerir () kullanarak doğru değeri bulabilirsiniz.

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

Bir DateTime nesnesi almak ve ardından Month özelliğini kontrol etmek için DateTime.Parse yöntemini kullanabilirsiniz. Bunun gibi bir şey yapın:

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

İşin püf noktası, bir DateTime nesnesi oluşturmak için geçerli bir tarih oluşturmaktır.


9

Bir ay sıralaması kullanabilirsiniz:

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

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

Enum.Parse () sözdiziminden% 100 emin değilim.


1
"Public Month ToInt (string Input) {...}" olması gerekir, ancak aksi takdirde doğrudur.
James Curran

1
Bunun eski bir yorum olduğunu biliyorum, ancak numaralamanıza 1'den başlamanız gerektiğini düşündüm, örneğin public enum Month { January = 1, Feburary }Ay yerine int'e çevirin.
eth0

@ eth0: Oops ... haklısın. Düzeltildi, işaret ettiğiniz için teşekkürler ;-)
Treb

7

Bunu yapmak için bir DateTime örneği oluşturmanız gerekmez. Bu kadar basit:

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

da-DKKültür üzerinde çalışıyorum , bu yüzden bu birim testi başarılı:

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

Bunu, açık bir CultureInfo'da geçirebileceğiniz bir aşırı yükleme oluşturmak için okuyucuya bir alıştırma olarak bırakacağım.


Güzel kullanım ToLower()- Aşırı yüklemelerden birinin dizeyi dönüştürdüğünün farkında değildim, using the casing rules of the specified cultureancak adil olmak gerekirse, yöntem adından bu işlevselliği karşılayabileceği açık değil.
David Clarke

1
Tamam, bu yüzden bunu LINQPad kullanarak test ediyordum ve benimde çalışmasını sağlayamıyorum CurrentCulture. Hem "January".ToLower(CultureInfo.CurrentCulture).Dump();ve "January".ToLower(new CultureInfo("en-NZ")).Dump();çıkış januaryama ay adlarını aktifleştirilir CurrentCulture.DateTimeFormat.MonthNames.
David Clarke

1
@DavidClarke Evet, sen edilir adlı bir işlev çağırma ToLoweray adlarını beri, benim kodunda ufak mantık hatası var :) Aslında olan da-DK bütün küçük harf olarak verilen. Bu nedenle, büyük / küçük harfe duyarlı olmayan bir eşleşmenin istenip istenmediğine bağlı olarak, ya girdiyi küçük harfle yazmamalı ya da tüm ay adlarını da küçültmelidir.
Mark Seemann

1
Evet, belgeleri using the casing rules of the specified culture, örneğin, aylar ve günler için büyük harfle yazılacağı şeklinde yorumluyordum CultureInfo. Bu, örneğinizde işe yarar çünkü ay isimleri küçük harftir. Yanıltmak için birim testleri kullanmanın etkili bir şekilde gösterilmesi. Örneğinizin uç bir durum olduğunu netleştirmek için düzenlemeye değer :-)
David Clarke

2

Ve bu soru sorulduktan yedi yıl sonra cevaplanırsa, bu karşılaştırmayı yerleşik yöntemler kullanarak yapmak mümkündür:

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

olur

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

Basitlik için bir uzatma yöntemine dönüştürülebilir. Aşağıdaki bir LINQPad örneğidir (dolayısıyla Dump()yöntem çağırır):

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

Çıktı ile:

False
True
True

Bu, IgnoreCase dize karşılaştırmasını kullanarak çok daha iyi bir çözümdür. Bu, OP'nin sorusu için iyi çalışıyor, ancak bu yöntemi DateTime.Month tarafından döndürülen aynı değere dönüştürmek için kullanmak istiyorsanız, sonuca +1 eklemenizi öneririm. OP'nin karşılaştırma gereksinimi hala karşılanıyor veya tabi ki.
iGanja

1

C # 3.0 (veya üstü) kullanıyorsanız, genişleticileri kullanabilirsiniz


O zaman evet, ne yazık ki kendi yönteminizin en zarif çözüm olacağını düşünüyorum.
Adam Naylor

1
@AdamNaylor: Uzatıcı nedir? cevabınızı bir örnekle açıklayabilir misiniz?
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

uyarı kodu Beta sürümündedir.


Kabul edilen cevap çok daha iyi.
James A Mohler

1

İspanyolca sürümünde C # koduna çeviriyorum, saygılar:

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

Yaptığım şey, bir biçim dizesi oluşturmak için SimpleDateFormat kullanmak ve metni bir tarihe ayrıştırmak ve ardından bundan ayı almaktı. Kod aşağıdadır:

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

Bu kod size yardımcı olur ...

using System.Globalization;

....

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

GetMonthName Yöntemi - dize döndürür ...

Bir ayı tam sayı olarak almak istiyorsanız, o zaman şunu kullanın -

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

Umarım size yardımcı olur !!!

Teşekkürler!!!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.