Come creare e utilizzare un IFormatProvider personalizzato per DateTime?
-
24-09-2019 - |
Domanda
I stava cercando di creare un'implementazione IFormatProvider
che riconoscere stringhe di formato personalizzato per oggetti DateTime. Qui è la mia realizzazione:
public class MyDateFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
{
return this;
}
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if(arg == null) throw new ArgumentNullException("arg");
if (arg.GetType() != typeof(DateTime)) return arg.ToString();
DateTime date = (DateTime)arg;
switch(format)
{
case "mycustomformat":
switch(CultureInfo.CurrentCulture.Name)
{
case "en-GB":
return date.ToString("ddd dd MMM");
default:
return date.ToString("ddd MMM dd");
}
default:
throw new FormatException();
}
}
mi aspettavo di essere in grado di utilizzarlo nel metodo DateTime.ToString(string format, IFormatProvider provider)
in questo modo, ma:
DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());
In questo esempio, l'esecuzione nella cultura degli Stati Uniti, il risultato è "00cu0Ao00or0aA"
, apparentemente perché le stringhe di formato DateTime standard, vengono interpretati.
Tuttavia, quando uso la stessa classe nel seguente modo:
DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);
ho capito quello che mi aspetto, vale a dire "Sun Jan 02"
Non capisco i diversi risultati. qualcuno potrebbe spiegare?
Grazie!
Soluzione
Controllo tipo DateTime.ToString
con spettacoli riflettenti che la struttura DateTime
utilizza il metodo DateTimeFormatInfo.GetInstance
per ottenere il provider da utilizzare per la formattazione. Il DateTimeFormatInfo.GetInstance
richiede un formattatore di tipo DateTimeFormatInfo
dal provider passata in, mai per ICustomFormmater
, quindi restituisce solo un esempio di un DateTimeFormatInfo
o CultureInfo
se non viene trovato alcun provider. Sembra che il metodo DateTime.ToString
non rispetta l'interfaccia ICustomFormatter
come il metodo StringBuilder.Format
fa, come i vostri String.Format
esempio mostra.
Sono d'accordo che il metodo DateTime.ToString
dovrebbe sostenere l'interfaccia ICustomFormatter
, ma non sembra al momento. Tutto ciò può essere cambiata o cambierà in .NET 4.0.
Altri suggerimenti
La breve spiegazione è che, mentre
DateTime.ToString(string format, IFormatProvider provider)
consente di passare nulla attuazione IFormatProvider
come uno dei suoi parametri, in realtà supporta solo 2 possibili tipi IFormatProvider
attuazione al suo interno del codice:
DateTimeFormatInfo
o CultureInfo
Se il parametro non può essere colato (usando as
) sia come o di quelli, il metodo imposterà CurrentCulture
.
String.Format
non è limitata da tali limiti.
Utilizzare il metodo di estensione:)
public static class FormatProviderExtension
{
public static string FormatIt(string format, object arg, IFormatProvider formatProvider)
{
if (arg == null) throw new ArgumentNullException("arg");
if (arg.GetType() != typeof(DateTime)) return arg.ToString();
DateTime date = (DateTime)arg;
switch (format)
{
case "mycustomformat":
switch (CultureInfo.CurrentCulture.Name)
{
case "en-GB":
return date.ToString("ddd dd MMM");
default:
return date.ToString("ddd MMM dd");
}
default:
throw new FormatException();
}
}
public static string ToString(this DateTime d, IFormatProvider formatProvider, string format)
{
return FormatIt(format, d, formatProvider);
}
}