Как создать и использовать пользовательский IFormatProvider для DateTime?

StackOverflow https://stackoverflow.com/questions/2382154

  •  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);
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top