Pregunta

Yo estaba tratando de crear una implementación IFormatProvider que reconocería las cadenas de formato personalizado para objetos DateTime. Aquí está mi aplicación:

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

Me estaba esperando a ser capaz de utilizarlo en el método DateTime.ToString(string format, IFormatProvider provider) como tal, sino que:

DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());

En este ejemplo, se ejecuta en la cultura de Estados Unidos, el resultado es "00cu0Ao00or0aA", al parecer porque las cadenas de formato estándar DateTime se interpretan.

Sin embargo, cuando se utiliza la misma clase de la siguiente manera:

DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);

consigo lo que esperaba, a saber "Sun Jan 02"

No entiendo los diferentes resultados. Podría explicar alguien?

Gracias!

¿Fue útil?

Solución

Comprobación del método DateTime.ToString con espectáculos Reflector que la estructura DateTime utiliza el método DateTimeFormatInfo.GetInstance para obtener el proveedor que se utiliza para formatear. El DateTimeFormatInfo.GetInstance solicita un formateador de tipo DateTimeFormatInfo del proveedor aprobada en, nunca por ICustomFormmater, por lo que sólo devuelve una instancia de un DateTimeFormatInfo o CultureInfo si no se encuentra ningún proveedor. Parece que el método DateTime.ToString no respeta la interfaz ICustomFormatter como el método StringBuilder.Format hace, como sus String.Format ejemplo muestra.

Estoy de acuerdo que el método DateTime.ToString debe apoyar la interfaz ICustomFormatter, pero no parece actualmente. Todo esto puede haber cambiado o cambiará en .NET 4.0.

Otros consejos

La breve explicación es que mientras

DateTime.ToString(string format, IFormatProvider provider)

permite pasar nada implementación IFormatProvider como uno de sus parámetros, que en realidad sólo admite 2 tipos posibles IFormatProvider implementar dentro del código:

DateTimeFormatInfo o CultureInfo

Si el parámetro no se puede lanzar (usando as), ya sea como o aquellos, el método será por defecto CurrentCulture.

String.Format no está limitada por tales límites.

método Uso extensión:)

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top