Como criar e usar um IFORMATPROVER personalizado para o DateTime?
-
24-09-2019 - |
Pergunta
Eu estava tentando criar um IFormatProvider
implementação que reconheceria seqüências de formato personalizado para objetos de data de dados. Aqui está minha implementação:
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();
}
}
Eu esperava poder usá -lo no DateTime.ToString(string format, IFormatProvider provider)
método como assim, mas:
DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());
Nesse exemplo, executando na cultura dos EUA, o resultado é "00cu0Ao00or0aA"
, Aparentemente, porque as seqüências de formato padrão do DateTime estão sendo interpretadas.
No entanto, quando uso a mesma classe da seguinte maneira:
DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);
Eu entendo o que espero, nomeadamente "Sun Jan 02"
Não entendo os diferentes resultados. Alguém poderia explicar?
Obrigado!
Solução
Verificando o DateTime.ToString
método com refletor mostra que o DateTime
estrutura usa o DateTimeFormatInfo.GetInstance
Método para que o provedor seja usado para formatação. o DateTimeFormatInfo.GetInstance
Solicita um formatador do tipo DateTimeFormatInfo
do provedor passou, nunca para ICustomFormmater
, então só retorna uma instância de um DateTimeFormatInfo
ou CultureInfo
Se nenhum provedor for encontrado. Parece que o DateTime.ToString
Método não honra o ICustomFormatter
interface como o StringBuilder.Format
método faz, como seu String.Format
Exemplo mostra.
Eu concordo que o DateTime.ToString
Método deve apoiar o ICustomFormatter
interface, mas não parece atualmente. Tudo isso pode ter mudado ou mudará no .NET 4.0.
Outras dicas
A curta explicação é que enquanto
DateTime.ToString(string format, IFormatProvider provider)
Permite passar por qualquer coisa implementando IFormatProvider
Como um de seus parâmetros, ele realmente suporta apenas 2 tipos possíveis implementando IFormatProvider
dentro de seu código:
DateTimeFormatInfo
ou CultureInfo
Se o seu parâmetro não puder ser lançado (usando as
) como um ou esses, o método não será CurrentCulture
.
String.Format
não é limitado por esses limites.
Use o método de extensão :)
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);
}
}