Question

Je suis en train de créer une implémentation IFormatProvider qui reconnaîtrait les chaînes de format personnalisé pour les objets DateTime. Voici mon implémentation:

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

Je comptais pouvoir l'utiliser dans la méthode DateTime.ToString(string format, IFormatProvider provider) comme si, mais:

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

Dans cet exemple, en cours d'exécution dans la culture des États-Unis, le résultat est "00cu0Ao00or0aA", apparemment parce que les chaînes au format standard DateTime sont interprétées.

Cependant, quand j'utilise la même classe de la manière suivante:

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

Je reçois ce que je pense, à savoir "Sun Jan 02"

Je ne comprends pas les différents résultats. Quelqu'un pourrait-il expliquer?

Merci!

Était-ce utile?

La solution

Vérification de la méthode DateTime.ToString avec réflecteur montre que la structure de DateTime utilise la méthode DateTimeFormatInfo.GetInstance pour obtenir le fournisseur à utiliser pour le formatage. Le DateTimeFormatInfo.GetInstance demande un formatter de type DateTimeFormatInfo du fournisseur transmis, jamais pour ICustomFormmater, il retourne seulement une instance d'un DateTimeFormatInfo ou CultureInfo si aucun fournisseur se trouve. Il semble que la méthode DateTime.ToString ne respecte pas l'interface ICustomFormatter comme la méthode StringBuilder.Format fait, comme exemple de String.Format montre.

Je suis d'accord que la méthode DateTime.ToString doit supporter l'interface ICustomFormatter, mais il ne semble pas actuellement. Tout cela peut être changé ou va changer dans .NET 4.0.

Autres conseils

L'explication courte est que tout

DateTime.ToString(string format, IFormatProvider provider)

vous permet de transmettre quoi que ce soit la mise en œuvre IFormatProvider comme l'un de ses paramètres, il prend en charge en fait seulement 2 types possibles de mise en œuvre IFormatProvider dans son code:

DateTimeFormatInfo ou CultureInfo

Si votre paramètre ne peut pas être casté (en utilisant as) comme l'un ou ceux, la méthode par défaut CurrentCulture.

String.Format ne se limite pas par de telles limites.

Utilisation méthode d'extension:)

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);
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top