У меня есть следующее утверждение.
timespan = timespan.FromSeconds(236541)
formattedTimeSpan = String.Format("{0} hr {1} mm {2} sec", Math.Truncate(timespan.TotalHours), timespan.Minutes, timespan.Seconds)
Я должен отформатируйте его как «hrs mn sec», если больше одного часа. Я хочу проверить это в String.Format выше.
Спасибо.
Одна из возможностей состоит в том, чтобы составить часть строки формата во множественном числе и записать:
formattedTimeSpan = String.Format("{0} hr{1} {2} mm {3} sec",
Math.Truncate(timespan.TotalHours),
Math.Truncate(timespan.TotalHours) == 1 ? "" : "s",
timespan.Minutes,
timespan.Seconds);
Это вставит "s" в вывод, если вывод говорит что-нибудь кроме " 1 час ».
Обратите внимание, что это не подходит для локализации: другие языки образуют множественное число иначе, чем английский.
Вероятно, самый чистый способ сделать это - написать собственный ICustomFormatter
. Вот пример удобного формата плюрализатора:
using System;
public class PluralFormatter : IFormatProvider, ICustomFormatter {
public object GetFormat(Type formatType) {
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg,
IFormatProvider formatProvider)
{
if (! formatProvider.Equals(this)) return null;
if (! format.StartsWith("^")) return null;
String[] parts = format.Split(new char[] {'^'});
int choice = ((int) arg) == 1 ? 1 : 2;
return String.Format("{0} {1}", arg, parts[choice]);
}
public static void Main() {
Console.WriteLine(String.Format(
new PluralFormatter(),
"{0:^puppy^puppies}, {1:^child^children}, and {2:^kitten^kittens}",
13, 1, 42
));
}
}
Результат, как можно было догадаться ( и как видно на ideone.com ):
13 puppies, 1 child, and 42 kittens
Никакой магии здесь нет. Зачем вам кодировать в любом формате условия , который может предложить
, когда вы можете писать код на C #?
Чтобы избежать дублирования кода, вы можете также преобразовать некоторые выражения в переменные и использовать для них условие:
timespan = timespan.FromSeconds(236541);
int hours = Math.Truncate(timespan.TotalHours);
string hoursUnit = hours == 1 ? "hr" : "hrs";
formattedTimeSpan = String.Format("{0}{1} {2} mm {3} sec",
hours, hoursUnit, timespan.Minutes, timespan.Seconds);
Нет "простого" способа сделать это.
Вы можете сделать это так
string templateSingleHour = "{0} hr {1} mm {2} sec";
string templateMultiHour = "{0} hrs {1} mm {2} sec";
string template = Math.Truncate(timespan.TotalHours) > 1 ? templateMultiHour :templateSingleHour;
formattedTimeSpan = String.Format(template ...)
или вот так
formattedTimeSpan = String.Format("{0} {3} {1} mm {2} sec", Math.Truncate(timespan.TotalHours), timespan.Minutes, timespan.Seconds, Math.Truncate(timespan.TotalHours) > 1 ? "hrs" : "hr");
FWIW, если ваше приложение когда-либо будет использоваться моими людьми, не говорящими по-английски, то это нетривиально. В блоге есть сообщение о проблеме на http://www.siao2.com/2007/07/24/4022881.aspx
Я использую несколько методов расширения, которые помогают мне в таких вещах:
public static string Inflect(this string noun, int count)
{
return (count == 1 || noun.EndsWith("s", StringComparison.InvariantCultureIgnoreCase)) ? noun : noun + "s";
}
public static string Of(this int count, string noun)
{
return string.Format("{0} {1}", count, noun.Inflect(count));
}
например:
«Час» .Inflect (1)
: Hour
"Час" .Inflect (2)
: Часы
0.Of ("час")
: "0 часов"
1.Of ("час")
: " 1 час »
5.Of (« час »)
:« 5 часов »
Следует использовать различные спецификаторы формата времени. Это помогает значительно упростить вызов Format ()
.
var timespan = TimeSpan.FromSeconds(236541);
var formattedTimeSpan = String.Format("{0:hh} hr{1} {0:mm} mm {0:ss} sec",
timespan, timespan.Hours != 1 ? "s" : "");