Что делает IFormatProvider?

95

Я играл с методом Datetime.ParseExact, и ему нужен IFormatProvider ...

Он работает с вводом нуля, но что именно он делает?

Moulde
источник
3
возможный дубликат Почему DateTime.ParseExact (String, String, IFormatProvider) нужен IFormatProvider? . Я голосую за то, чтобы закрыть предложение новым, потому что он сформулирован лучше и дает лучший ответ.
nawfal

Ответы:

62

В дополнение к ответу Яна Бойда:

Также CultureInfoреализует этот интерфейс и может быть использован в вашем случае. Так, например, вы можете разобрать строку даты на французском языке; вы могли бы использовать

var ci = new CultureInfo("fr-FR");
DateTime dt = DateTime.ParseExact(yourDateInputString, yourFormatString, ci);
Андрей Рыня
источник
2
Похоже, что в .NET Framework 4.6 больше нет перегрузки, соответствующей вашему примеру. DateTime.ParseExact(string, string, IFormatProvider)Я считаю, что вы должны использовать вместо этого - как таковые: DateTime.ParseExact("20160409 111559","yyyyMMdd HHmmss",CultureInfo.CurrentCulture)
Джеймс Кинг
1
В .NET Framework 4.6.2 отсутствуют входные параметры, как вы указываете. Я использую только два, и все работает нормально. DateTime dt = DateTime.Parse(yourDateInputString, ci);Исправьте свой ответ.
DmitryBoyko
1
Извините, ребята, в мой ответ было внесено давно назревшее обновление.
Андрей Рыня
49

IFormatProviderИнтерфейс обычно реализуется для вас в CultureInfoклассе, например:

  • CultureInfo.CurrentCulture
  • CultureInfo.CurrentUICulture
  • CultureInfo.InvariantCulture
  • CultureInfo.CreateSpecificCulture("de-CA") //German (Canada)

Интерфейс является шлюзом для функции, которая получает набор данных, относящихся к культуре, из культуры. Два общедоступных объекта культуры, которые IFormatProviderможно запросить:

Обычно это работает, когда вы просите IFormatProviderпредоставить вам DateTimeFormatInfoобъект:

DateTimeFormatInfo format;
format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
if (format != null)
   DoStuffWithDatesOrTimes(format);

Также есть внутренняя осведомленность о том, что любой IFormatProviderинтерфейс, вероятно, реализуется классом, который является наследником CultureInfoили наследником DateTimeFormatInfo, поэтому вы можете напрямую преобразовать интерфейс:

CultureInfo info = provider as CultureInfo;
if (info != null)
   format = info.DateTimeInfo;
else
{
   DateTimeFormatInfo dtfi = provider as DateTimeFormatInfo;
   if (dtfi != null)
       format = dtfi;
   else
       format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
}

if (format != null)
   DoStuffWithDatesOrTimes(format);

Но не делай этого

Вся эта тяжелая работа уже написана для вас:

Чтобы получить DateTimeFormatInfoотIFormatProvider :

DateTimeFormatInfo format = DateTimeFormatInfo.GetInstance(provider);

Чтобы получить NumberFormatInfoотIFormatProvider :

NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);

Ценность в IFormatProviderтом, что вы создаете свои собственные объекты культуры. Если они реализуют IFormatProviderи возвращают запрашиваемые объекты, вы можете обойти встроенные культуры.

Вы также можете использовать IFormatProviderдля передачи произвольных объектов культуры - через IFormatProvider. Например, имя бога в разных культурах

  • Бог
  • Бог
  • Иегова
  • Яхве
  • יהוה
  • אהיה אשר אהיה

Это позволяет вашему пользовательскому LordsNameFormatInfoклассу перемещаться внутри IFormatProvider, и вы можете сохранить идиому.

На самом деле вам никогда не понадобится вызывать GetFormatметод самого IFormatProviderсебя.

Когда вам понадобится, IFormatProviderвы можете передать CultureInfoобъект:

DateTime.Now.ToString(CultureInfo.CurrentCulture);

endTime.ToString(CultureInfo.InvariantCulture);

transactionID.toString(CultureInfo.CreateSpecificCulture("qps-ploc"));

Примечание : любой код передается в общественное достояние. Ссылка на авторство не требуется.

Ян Бойд
источник
18

Передача null в IFormatProviderкачестве неправильного способа сделать это. Если на компьютере пользователя настроен настраиваемый формат даты / времени, у вас возникнут проблемы с синтаксическим анализом и преобразованием в строку. Я только что исправил ошибку, когда кто-то передавал null как IFormatProvider при преобразовании в строку.

Вместо этого вы должны использовать CultureInfo.InvariantCulture

Неправильно:

string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", null);

Верный:

string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Тим
источник
2
Есть ли причина, по которой мы должны использовать CultureInfo.InvariantCultureвместо CultureInfo.CurrentCulture?
Стивен Бухер
5
InvariantCulture - это особая культура, которая гарантированно будет всегда существовать на любой машине и всегда будет преобразовывать и возвращать одни и те же значения. CurrentCulture - это культура текущего потока. Это может быть разным, и если вы не используете одну и ту же культуру для преобразования в строку и синтаксического анализа, вы получите ошибки формата ...
Тим
5
@StephenBooher по nullумолчанию будет CultureInfo.CurrentCulture. См. Вызов в справочном источнике , если вы проследите цепочку вызовов, в конечном итоге будет заменен нуль, DateTimeFormatInfo.CurrentInfoкоторый эквивалентен тем, какие CultureInfo.CurrentCultureвыходы.
Скотт Чемберлен
InvariantCulture - это то, что я искал. Спасибо
Chicowitz
5

IFormatProvider предоставляет информацию о культуре для рассматриваемого метода. DateTimeFormatInfo реализует IFormatProvider и позволяет указать формат, в котором должны отображаться дата / время. Примеры можно найти на соответствующих страницах MSDN.

Raithlin
источник
2

Автор MSDN

.NET Framework включает следующие три предопределенные реализации IFormatProvider для предоставления информации, зависящей от языка и региональных параметров, которая используется при форматировании или анализе числовых значений и значений даты и времени:

  1. NumberFormatInfoКласс, который содержит информацию, которая используется для форматирования чисел, такие как валюта, разделителя тысяч и символов десятичного разделителя для конкретной культуры. Для получения информации о стандартных строках формата, распознаваемых NumberFormatInfoобъектом и используемых в операциях числового форматирования, см. Разделы Стандартные строки числового формата и Строки настраиваемого числового формата.
  2. DateTimeFormatInfoКласс, который содержит информацию, которая используется для даты и времени в формате, например, дата и время символов разделителей для конкретной культуры или порядка и формы компонентов года, месяца и дня Дейта. Для получения информации о стандартных строках формата, распознаваемых DateTimeFormatInfoобъектом и используемых в операциях числового форматирования, см. Разделы Стандартные строки формата даты и времени и Строки настраиваемого формата даты и времени.
  3. CultureInfoКласс, который представляет собой особую культуру. Его GetFormatметод возвращает объект NumberFormatInfoили язык DateTimeFormatInfo, зависящий от языка и региональных параметров, в зависимости от того, используется ли CultureInfoобъект в операции форматирования или анализа, которая включает числа или даты и время.

.NET Framework также поддерживает настраиваемое форматирование. Обычно это включает создание класса форматирования, который реализует как IFormatProvider, так и ICustomFormatter. Затем экземпляр этого класса передается в качестве параметра методу, который выполняет операцию настраиваемого форматирования, например String.Format(IFormatProvider, String, Object[]).

Большие глаза
источник
1

Класс DateTimeFormatInfo реализует этот интерфейс, поэтому он позволяет вам управлять форматированием ваших строк DateTime.

Герри Шенк
источник