2010-10-13 27 views
1

Ainsi par exemple laisse dire quand je string.format une date et utilise la chaîne "ou" dans le modèle de format je veux que converti à la valeur ordinale de la date.String.Format et DateTimeFormatInfo sont-ils enfichables/extensibles?

-à-dire

string.Format("{0:ddor MMM yyyy}.", DateTime.Now) 

devrait sortie

1st Jan 2010 

Voir ci-dessous pour savoir comment calculer les nombres ordinaux

Is there an easy way in .NET to get "st", "nd", "rd" and "th" endings for numbers?

Répondre

2

Il semble qu'il n'y ait pas quelque chose comme ça.

La façon la plus recommandée pour le faire:

var d = DateTime.Now; 
var result2 = String.Format("{0:dd}{1} {2:MMM yyyy}", d, Ordinal(d.Day), d); 

Une façon très hacky pour y parvenir est de créer une coutume IFormatProvider. L'OMI, il est juste beaucoup de mal, mais juste pour montrer une autre façon ... (je n'ai pas beaucoup d'expérience avec cela, il pourrait ne pas être très « correct »)

using System; 

namespace Test 
{ 
    class Program 
    { 
     public static string Ordinal(int number) 
     { 
      string suffix = String.Empty; 

      int ones = number % 10; 
      int tens = (int)Math.Floor(number/10M) % 10; 

      if (tens == 1) 
      { 
       suffix = @"\t\h"; 
      } 
      else 
      { 
       switch (ones) 
       { 
        case 1: 
         suffix = @"\s\t"; 
         break; 

        case 2: 
         suffix = @"\n\d"; 
         break; 

        case 3: 
         suffix = @"\r\d"; 
         break; 

        default: 
         suffix = @"\t\h"; 
         break; 
       } 
      } 
      return suffix; 
     } 

     public class MyFormat : IFormatProvider, ICustomFormatter 
     { 
      public object GetFormat(Type formatType) 
      { 
       return (formatType == typeof(ICustomFormatter)) ? this : null; 

      } 

      public string Format(string format, object arg, IFormatProvider formatProvider) 
      { 
       var d = (DateTime)arg; 

       var or = Ordinal(d.Day); 

       format = format.Replace("or", or); 

       return d.ToString(format); 
      } 
     } 
     static void Main(string[] args) 
     { 
      var result = String.Format(new MyFormat(), "{0:ddor MMM yyyy}.", DateTime.Now); 

      return; 
     } 
    } 
} 

More info on Custom IFormatProvider

+0

Merci pour la réponse Bruno. Cependant, je cherchais une méthode qui n'était pas si intrusive pour l'utilisateur. – Simon

1

Les fournisseurs de format sont connectables, mais pour autant que je sache, vous ne pouvez pas configurer un fournisseur de format par défaut pour un type donné. Les méthodes qui acceptent les chaînes de format par convention ont généralement aussi une surcharge qui prend un IFormatProvider. Vous pouvez implémenter deux classes telles que MyFormatProvider: IFormatProvider et MyCustomFormatter: ICustomFormatter.

Lorsqu'une chaîne de format telle que "{0: dd} {0: ou} {0: MMM} {0: yyyy}" est traitée, votre ICustomFormatter sera appelée 4 fois, avec "dd", "ou "," MMM ", et" yyyy "comme les paramètres afin qu'il puisse formater chaque partie séparément. Vous devrez simplement gérer le cas "ou" et passer le reste au fournisseur de format par défaut. Toutefois, l'appelant devra toujours passer une instance de votre fournisseur de format personnalisé lors du formatage. Par exemple:

string str = String.Format(MyFormatProvider.Default, "{0:dd}{0:or} {0:MMM} {0:yyyy}", date); 

Autant que je sache, il n'y a pas échapper à cette exigence. J'ai cherché un meilleur moyen il y a un moment quand j'avais créé une chaîne de format DateTime "relative" qui affichait des DateTimes comme "il y a 1 heure", "il y a 3 jours", etc. Impossible de trouver un moyen d'éviter explicitement passer mon IFormatProvider personnalisé.