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!

Foi útil?

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);
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top