2010-10-13 3 views
1

Так, например, скажем, когда я string.format дата и использую строку «или» в шаблоне формата, я хочу, чтобы это преобразовало в порядковое значение Date.Является ли String.Format и DateTimeFormatInfo подключаемым/расширяемым?

т.е.

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

должен вывести

1st Jan 2010 

Ниже описывается, как вывести порядковые номера

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

ответ

2

Кажется, есть не что-то вроде этого.

Наиболее рекомендуемый способ сделать это:

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

очень Hacky способ добиться этого заключается в создании пользовательских IFormatProvider. IMO это просто много хлопот, но только, чтобы показать альтернативный способ ... (я не имею большого опыта работы с этим, это может быть не очень «правильно»)

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

Спасибо за ответ Бруно. однако я искал метод, который не был настолько навязчивым для пользователя. – Simon

1

Поставщики форматов подключаются, но, насколько я знаю, вы не можете настроить поставщика формата по умолчанию для данного типа. Методы, которые принимают формат строк по соглашению, обычно также имеют перегрузку, которая принимает IFormatProvider. Вы можете реализовать два класса, такие как MyFormatProvider: IFormatProvider и MyCustomFormatter: ICustomFormatter.

Когда обрабатывается строка формата, такая как «{0: dd} {0: или} {0: MMM} {0: yyyy}", ваш ICustomFormatter будет вызываться 4 раза, с "dd", "или «, MMM» и «yyyy» в качестве параметров, чтобы он мог форматировать каждую часть отдельно. Вам просто нужно обработать «или» случай и передать остальные на поставщика формата по умолчанию.

Однако при форматировании вызывающему абоненту все равно необходимо передать экземпляр поставщика настраиваемого формата. Например:

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

Насколько я знаю, этого требования не избежать. Я искал лучший путь назад, когда создал «относительную» строку формата DateTime, которая отображала DateTimes как «1 час назад», «3 дня назад» и т. Д. Не удалось найти способ избежать явного передать мой пользовательский метод IFormatProvider.

Смежные вопросы