Является ли String.Format и DateTimeFormatInfo подключаемыми / расширяемыми?
Например, давайте скажем, когда я string.format для даты и использую строку "или" в шаблоне формата, который я хочу преобразовать в порядковое значение даты.
т.е.
string.Format("{0:ddor MMM yyyy}.", DateTime.Now)
должен выводить
1st Jan 2010
Смотрите ниже, как получить порядковые номера
Есть ли в.NET простой способ получить окончание чисел "st", "nd", "rd" и "th"?
2 ответа
Кажется, что-то не так.
Самый рекомендуемый способ сделать это:
var d = DateTime.Now;
var result2 = String.Format("{0:dd}{1} {2:MMM yyyy}", d, Ordinal(d.Day), d);
Очень хакерский способ добиться этого - создать кастом IFormatProvider
, ИМО, это просто много проблем, но просто чтобы показать альтернативный путь... (У меня нет большого опыта с этим, это может быть не очень "правильно")
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;
}
}
}
Поставщики форматов являются подключаемыми, но, насколько я знаю, вы не можете настроить поставщика форматов по умолчанию для данного типа. Методы, которые принимают строки формата по соглашению, как правило, также имеют перегрузку, которая принимает IFormatProvider. Вы можете реализовать два класса, таких как MyFormatProvider: IFormatProvider и MyCustomFormatter: ICustomFormatter.
При обработке строки формата, такой как "{0:dd}{0:or} {0:MMM} {0:yyyy}", ваш ICustomFormatter будет вызываться 4 раза, с "dd", "or", "MMM", и" гггг "в качестве параметров, чтобы он мог отформатировать каждую часть отдельно. Вы просто должны обработать случай "или" и передать остальное поставщику формата по умолчанию.
Тем не менее, при форматировании вызывающей стороне все равно нужно будет передать экземпляр вашего поставщика нестандартного формата. Например:
string str = String.Format(MyFormatProvider.Default, "{0:dd}{0:or} {0:MMM} {0:yyyy}", date);
Насколько я знаю, от этого требования не уйти. Некоторое время назад я искал лучший способ, когда создал "относительную" строку формата DateTime, которая отображала бы такие значения DateTime, как "1 час назад", "3 дня назад" и т. Д. Не удалось найти способ избежать явного передать мой пользовательский IFormatProvider.