Как создать и использовать пользовательский IFormatProvider для DateTime?
-
24-09-2019 - |
Вопрос
Я пытался создать IFormatProvider
Реализация, которая распознает бы строки пользовательских форматов для объектов DateTime. Вот моя реализация:
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();
}
}
Я ожидал, что сможет использовать его в DateTime.ToString(string format, IFormatProvider provider)
метод так, но:
DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());
В этом примере, работающих в культуре США, результат "00cu0Ao00or0aA"
, по-видимому, потому что стандартные строки формата DateTime интерпретируются.
Однако, когда я использую один и тот же класс следующим образом:
DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);
Я получаю то, что я ожидаю, а именно "Sun Jan 02"
Я не понимаю разных результатов. Может кто-то объяснить?
Спасибо!
Решение
Проверка DateTime.ToString
Метод с отражателем показывает, что DateTime
Структура использует то DateTimeFormatInfo.GetInstance
Способ получения поставщика будет использоваться для форматирования. То DateTimeFormatInfo.GetInstance
Запрашивает форматированный тип DateTimeFormatInfo
от провайдера прошел, никогда не для ICustomFormmater
, поэтому он возвращает только экземпляр DateTimeFormatInfo
или CultureInfo
Если провайдер не найден. Кажется, что DateTime.ToString
Метод не соблюдает ICustomFormatter
интерфейс вроде StringBuilder.Format
метод делает, как ваш String.Format
Пример показывает.
Я согласен, что DateTime.ToString
Метод должен поддерживать ICustomFormatter
Интерфейс, но в настоящее время он не кажется. Это все может измениться или изменится в .NET 4.0.
Другие советы
Краткое объяснение это то, что пока
DateTime.ToString(string format, IFormatProvider provider)
давайте пройдем что-нибудь реализацию IFormatProvider
Как один из его параметров, он на самом деле поддерживает только 2 возможных типа, реализующихся IFormatProvider
Внутри это код:
DateTimeFormatInfo
или CultureInfo
Если ваш параметр не может быть выбран (используя as
) как либо или те, метод будет по умолчанию CurrentCulture
.
String.Format
не ограничен такими оценками.
Используйте метод расширения :)
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);
}
}