Що робить IFormatProvider?


93

Я бавився з методом Datetime.ParseExact, і він хоче IFormatProvider ...

Це працює, вводячи нуль, але що саме він робить?


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

Відповіді:


61

Крім відповіді Яна Бойда:

Також 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);перегляньте свою відповідь.
Розробник

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.




2

за MSDN

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

  1. NumberFormatInfoКлас, який містить інформацію, яка використовується для форматування чисел, такі як валюта, роздільник тисяч і символів десяткового роздільника для конкретної культури. Інформацію про заздалегідь визначені рядки формату, розпізнані NumberFormatInfoоб’єктом і використовувані в операціях числового форматування, див. У рядках Стандартний числовий формат та Рядки користувацького числового формату.
  2. DateTimeFormatInfoКлас, який містить інформацію, яка використовується для дати і часу в форматі, наприклад, дата і час символів роздільників для конкретної культури або порядку і форми компонентів року, місяця і дня Дейта. Для отримання інформації про визначені рядки формату, розпізнані aDateTimeFormatInfo об’єктом і використовувані в операціях числового форматування, див. У розділі Стандартні рядки формату дати та часу та Спеціальні рядки формату дати та часу.
  3. CultureInfoКлас, який представляє собою особливу культуру. Його GetFormatметод повертає специфічну для культури NumberFormatInfoабо DateTimeFormatInfoоб’єкт, залежно від того, чи використовується CultureInfoоб’єкт в операції форматування або синтаксичного аналізу, що включає числа або дати та час.

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.