So erstellen und einen benutzerdefinierten IFormatProvider für Datetime verwenden?
-
24-09-2019 - |
Frage
Ich habe versucht, eine IFormatProvider
Implementierung zu erstellen, die benutzerdefinierten Formatstrings für Datetime-Objekte erkennen würde. Hier ist meine Implementierung:
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();
}
}
Ich hatte erwartet, wie so in der Lage sein es in der DateTime.ToString(string format, IFormatProvider provider)
Methode zu verwenden, aber:
DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());
In diesem Beispiel in der US-Kultur läuft, ist das Ergebnis "00cu0Ao00or0aA"
, offenbar weil die Standard-Datetime-Format-Strings interpretiert werden.
Allerdings, wenn ich die gleiche Klasse wie folgt verwendet werden:
DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);
Ich bekomme, was ich erwarte, nämlich "Sun Jan 02"
Ich verstehe nicht, die unterschiedlichen Ergebnisse. Könnte jemand erklären?
Danke!
Lösung
Überprüfen der DateTime.ToString
Methode mit Reflector zeigt, dass die DateTime
Struktur der DateTimeFormatInfo.GetInstance
Methode verwendet den Anbieter zu bekommen, um für die Formatierung verwendet werden. Die DateTimeFormatInfo.GetInstance
fordert einen Formatierer vom Typ DateTimeFormatInfo
vom Provider übergeben, nie für ICustomFormmater
, so dass es nur eine Instanz eines DateTimeFormatInfo
oder CultureInfo
zurückgibt, wenn kein Anbieter gefunden wird. Es scheint, dass die DateTime.ToString
Methode nicht die ICustomFormatter
Schnittstelle nicht einlöst wie die StringBuilder.Format
Verfahren der Fall ist, wie Ihr String.Format
Beispiel zeigt.
Ich bin damit einverstanden, dass die DateTime.ToString
Methode, um die ICustomFormatter
Schnittstelle unterstützen soll, aber es scheint nicht zu aktuell. Das alles kann sich geändert haben oder wird in .NET 4.0 ändern.
Andere Tipps
Die kurze Erklärung ist, dass während
DateTime.ToString(string format, IFormatProvider provider)
können Sie etwas passieren Umsetzung IFormatProvider
als eines seiner Parameter, es tatsächlich unterstützt nur zwei mögliche Arten der Umsetzung IFormatProvider
Inneren Code:
DateTimeFormatInfo
oder CultureInfo
Wenn Ihr Parameter kann nicht gegossen werden (mit as
) als entweder oder denjenigen, wird das Verfahren auf CurrentCulture
Standard.
String.Format
wird durch solche Grenzen nicht darauf beschränkt.
Mit Erweiterungsmethode:)
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);
}
}