Come analizzare il nome di un mese (stringa) in un numero intero per il confronto in C#?
Domanda
Devo essere in grado di confrontare alcuni nomi di mesi che ho in un array.
Sarebbe bello se ci fosse un modo diretto come:
Month.toInt("January") > Month.toInt("May")
La mia ricerca su Google sembra suggerire che l'unico modo è scrivere il proprio metodo, ma questo sembra un problema abbastanza comune che penserei che sarebbe già stato implementato in .Net, qualcuno l'ha già fatto prima?
Soluzione
DateTime.ParseExact(monthName, "MMMM", CultureInfo.CurrentCulture ).Month
Anche se, per i tuoi scopi, probabilmente starai meglio semplicemente creando una Dictionary<string, int>
mappatura del nome del mese al suo valore.
Altri suggerimenti
Potresti fare qualcosa del genere:
Convert.ToDate(month + " 01, 1900").Month
Se usi il metodo DateTime.ParseExact()
- che molte persone hanno suggerito, dovresti considerare attentamente cosa vuoi che accada quando l'applicazione viene eseguita in un ambiente non inglese!
In Danimarca, quale tra ParseExact("Januar", ...)
e ParseExact("January", ...)
dovrebbe funzionare e quale dovrebbe fallire?
Questa sarà la differenza tra CultureInfo.CurrentCulture
e CultureInfo.InvariantCulture
.
È possibile utilizzare il metodo DateTime.Parse per ottenere un oggetto DateTime e quindi controllare la sua proprietà Month. Fai qualcosa del genere:
int month = DateTime.Parse("1." + monthName + " 2008").Month;
Il trucco è costruire una data valida per creare un oggetto DateTime.
Puoi usare un enum di mesi:
public enum Month
{
January,
February,
// (...)
December,
}
public Month ToInt(Month Input)
{
return (int)Enum.Parse(typeof(Month), Input, true));
}
Non sono sicuro al 100% sulla sintassi di enum.Parse (), comunque.
Non è necessario creare un'istanza DateTime per farlo. È semplice come questo:
public static class Month
{
public static int ToInt(this string month)
{
return Array.IndexOf(
CultureInfo.CurrentCulture.DateTimeFormat.MonthNames,
month.ToLower(CultureInfo.CurrentCulture))
+ 1;
}
}
Sto correndo sulla cultura da-DK
, quindi questo test unitario ha superato:
[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);
}
Lascio che sia un esercizio per il lettore creare un sovraccarico in cui puoi passare in un CultureInfo esplicito.
Una semplice soluzione sarebbe quella di creare un dizionario con nomi e valori. Quindi usando Contains () puoi trovare il valore giusto.
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;
}
}
E rispondendo a questa domanda sette anni dopo che è stata posta la domanda, è possibile fare questo confronto utilizzando metodi integrati:
Month.toInt("January") > Month.toInt("May")
diventa
Array.FindIndex( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames,
t => t.Equals("January", StringComparison.CurrentCultureIgnoreCase)) >
Array.FindIndex( CultureInfo.CurrentCulture.DateTimeFormat.MonthNames,
t => t.Equals("May", StringComparison.CurrentCultureIgnoreCase))
Che può essere sottoposto a refactoring in un metodo di estensione per semplicità.Quello che segue è un esempio LINQPad (da cui il file Dump()
chiamate di metodo):
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));
}
}
Con uscita:
False
True
True
Se si utilizza c # 3.0 (o versioni successive) è possibile utilizzare gli extender
Lo traduco in codice C # in versione spagnola, per quanto riguarda:
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";
}
}
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
il codice di avvertenza è in versione Beta.
Quello che ho fatto è stato usare SimpleDateFormat per creare una stringa di formato e analizzare il testo in una data, quindi recuperare il mese da quella. Il codice è sotto:
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();