O que IFormatProvider faz?

Respostas:

61

Além da resposta de Ian Boyd:

Também CultureInfoimplementa essa interface e pode ser usada no seu caso. Portanto, você pode analisar uma string de data em francês, por exemplo; você poderia usar

var ci = new CultureInfo("fr-FR");
DateTime dt = DateTime.ParseExact(yourDateInputString, yourFormatString, ci);
Andrei Rînea
fonte
2
Não parece mais haver uma sobrecarga que corresponda ao seu exemplo no .NET Framework 4.6. Você deve usar em DateTime.ParseExact(string, string, IFormatProvider)vez disso, eu acredito - como tal: DateTime.ParseExact("20160409 111559","yyyyMMdd HHmmss",CultureInfo.CurrentCulture)
James King de
1
No .NET Framework 4.6.2, não há parâmetros de entrada conforme você aponta. Eu uso apenas dois e funciona bem DateTime dt = DateTime.Parse(yourDateInputString, ci);Por favor, revise sua resposta.
Desenvolvedor
1
Desculpe pessoal, uma atualização muito atrasada foi feita à minha resposta.
Andrei Rînea
49

A IFormatProviderinterface é normalmente implementada para você por uma CultureInfoclasse, por exemplo:

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

A interface é um portal para uma função obter um conjunto de dados específicos da cultura de uma cultura. Os dois objetos de cultura comumente disponíveis que IFormatProviderpodem ser consultados são:

A maneira como normalmente funcionaria é você pedir ao IFormatProviderpara lhe dar um DateTimeFormatInfoobjeto:

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

Também há conhecimento interno de que qualquer IFormatProviderinterface provavelmente está sendo implementada por uma classe que desce CultureInfoou desce de DateTimeFormatInfo, então você pode lançar a interface diretamente:

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);

Mas não faça isso

Todo esse trabalho árduo já foi escrito para você:

Para obter um DateTimeFormatInfode umIFormatProvider :

DateTimeFormatInfo format = DateTimeFormatInfo.GetInstance(provider);

Para obter um NumberFormatInfode umIFormatProvider :

NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);

O valor de IFormatProvideré que você cria seus próprios objetos de cultura. Contanto que eles implementem IFormatProvidere retornem os objetos pelos quais são solicitados, você pode ignorar as culturas integradas.

Você também pode usar IFormatProvidercomo uma forma de passar objetos de cultura arbitrários - por meio do IFormatProvider. Por exemplo, o nome de deus em diferentes culturas

  • Deus
  • Deus
  • Jeová
  • Yahwe
  • יהוה
  • אהיה אשר אהיה

Isso permite que sua LordsNameFormatInfoclasse personalizada circule dentro de um IFormatProvider, e você pode preservar o idioma.

Na realidade, você nunca precisará chamar o GetFormatmétodo de IFormatProvidersi mesmo.

Sempre que precisar de um, IFormatProvidervocê pode passar um CultureInfoobjeto:

DateTime.Now.ToString(CultureInfo.CurrentCulture);

endTime.ToString(CultureInfo.InvariantCulture);

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

Nota : Qualquer código é lançado em domínio público. Nenhuma atribuição necessária.

Ian Boyd
fonte
18

Passar nulo como IFormatProvidernão é a maneira correta de fazer isso. Se o usuário tiver um formato de data / hora personalizado em seu PC, você terá problemas para analisar e converter para string. Acabei de consertar um bug em que alguém passou null como IFormatProvider ao converter para string.

Em vez disso, você deve usar CultureInfo.InvariantCulture

Errado:

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

Corrigir:

string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Tim
fonte
2
Existe alguma razão que devemos usar em CultureInfo.InvariantCulturevez de CultureInfo.CurrentCulture?
Stephen Booher
5
InvariantCulture é uma cultura especial que tem a garantia de sempre existir em qualquer máquina e sempre será convertida e analisada de volta para os mesmos valores. CurrentCulture é a cultura do segmento atual. Isso pode variar e se você não usar a mesma cultura para converter para string e analisar, você obterá erros de formato ...
Tim
5
@StephenBooher passando nullo padrão para CultureInfo.CurrentCulture. Veja a chamada na fonte de referência , se você seguir a cadeia de chamadas, o nulo eventualmente será substituído por DateTimeFormatInfo.CurrentInfoqual é equivalente a quais CultureInfo.CurrentCulturesaídas.
Scott Chamberlain
InvariantCulture é o que eu estava procurando. Obrigado
Chicowitz de
5

IFormatProvider fornece informações de cultura para o método em questão. DateTimeFormatInfo implementa IFormatProvider e permite que você especifique o formato no qual deseja que sua data / hora seja exibida. Os exemplos podem ser encontrados nas páginas relevantes do MSDN.

Raithlin
fonte
2

Por MSDN

O .NET Framework inclui as seguintes três implementações predefinidas de IFormatProvider para fornecer informações específicas da cultura que são usadas na formatação ou análise de valores numéricos e de data e hora:

  1. A NumberFormatInfoclasse, que fornece informações usadas para formatar números, como moeda, separador de milhares e símbolos separadores decimais para uma cultura específica. Para obter informações sobre as strings de formato predefinidas reconhecidas por um NumberFormatInfoobjeto e usadas em operações de formatação numérica, consulte Strings de formato numérico padrão e Strings de formato numérico personalizado.
  2. A DateTimeFormatInfoclasse, que fornece informações que são usadas para formatar datas e horas, como os símbolos separadores de data e hora para uma cultura específica ou a ordem e formato dos componentes de ano, mês e dia de uma data. Para obter informações sobre as strings de formato predefinidas reconhecidas por um DateTimeFormatInfoobjeto e usadas em operações de formatação numérica, consulte Strings de formato de data e hora padrão e Strings de formato de data e hora personalizados.
  3. A CultureInfoclasse, que representa uma cultura particular. Seu GetFormatmétodo retorna um objeto NumberFormatInfoou específico da cultura DateTimeFormatInfo, dependendo se o CultureInfoobjeto é usado em uma operação de formatação ou análise que envolve números ou datas e horas.

O .NET Framework também oferece suporte à formatação personalizada. Isso normalmente envolve a criação de uma classe de formatação que implementa IFormatProvider e ICustomFormatter. Uma instância dessa classe é então passada como um parâmetro para um método que executa uma operação de formatação personalizada, como String.Format(IFormatProvider, String, Object[]).

Olhos grandes
fonte
1

A classe DateTimeFormatInfo implementa essa interface, portanto, permite que você controle a formatação de suas strings DateTime.

Gerrie Schenck
fonte