formato fecha c# iformatprovider

c# - fecha - datetime format



¿Cómo crear y usar un IFormatProvider personalizado para DateTime? (3)

Estaba intentando crear una implementación de IFormatProvider que reconociera cadenas de formato personalizado para los objetos DateTime. Aquí está mi implementació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(); } }

Esperaba poder usarlo en el método DateTime.ToString(string format, IFormatProvider provider) , pero:

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

En ese ejemplo, al ejecutarse en la Cultura de EE. UU., El resultado es "00cu0Ao00or0aA" , aparentemente porque se están interpretando las cadenas de formato de fecha y "00cu0Ao00or0aA" estándar.

Sin embargo, cuando uso la misma clase de la siguiente manera:

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

Obtengo lo que espero, a saber, "Sun Jan 02"

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

¡Gracias!


La breve explicación es que mientras

DateTime.ToString(string format, IFormatProvider provider)

le permite pasar cualquier cosa que implemente IFormatProvider como uno de sus parámetros, en realidad solo admite 2 tipos posibles que implementan IFormatProvider dentro de su código:

DateTimeFormatInfo o CultureInfo

Si su parámetro no se puede convertir (usando as ) como ninguno de estos, el método se establecerá de forma predeterminada en CurrentCulture .

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


La comprobación del método DateTime.ToString con Reflector muestra que la estructura DateTime utiliza el método DateTimeFormatInfo.GetInstance para que el proveedor se utilice para el formateo. DateTimeFormatInfo.GetInstance solicita un formateador de tipo DateTimeFormatInfo del proveedor que se le ICustomFormmater , nunca para ICustomFormmater , por lo que solo devuelve una instancia de DateTimeFormatInfo o CultureInfo si no se encuentra ningún proveedor. Parece que el método DateTime.ToString no ICustomFormatter interfaz ICustomFormatter como lo hace el método StringBuilder.Format , como muestra el ejemplo de String.Format .

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


Usa el método de 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); } }