Пользовательские форматы строк TimeSpan - PullRequest
4 голосов
/ 20 августа 2010

Я хочу отформатировать TimeSpans в C # следующим образом:

ххх дней (с) гггг часов (с) zzz минут (с)

Условия:

  1. Дополнительные секунды должны быть усечены

  2. дней - это самая большая единица, которую я хочу. Я хочу, чтобы 34 дня отображались как 34 дня, а не как 1 месяц 4 дня и т. Д.

  3. Если временной интервал меньше одного дня, я не хочу, чтобы часть дня отображалась. Аналогично, если span меньше 1 часа, я хочу, чтобы отображалась только минутная часть.

Есть ли способ сделать это, используя строки встроенного формата, или нет другого способа, кроме как написать свою собственную функцию?

Редактировать: в настоящее время использую свою собственную функцию для этого. Время ввода в минутах занимает (TimeSpan.TotalMinutes):

private static string GetTimeStringFromMinutes(double p)
        {
            var minutes = (int) p;
            int hours = minutes / 60;
            minutes = minutes % 60;
            int days = hours/24;
            hours = hours%24;
            string dayPart = days + " day(s) ";
            string hoursPart = hours + " hour(s) ";
            string minutesPart = minutes + " minute(s)";
            if (days != 0)
                return (dayPart + hoursPart + minutesPart);
            if (hours != 0)
                return (hoursPart + minutesPart);
            return (minutesPart);
        }

Ответы [ 4 ]

6 голосов
/ 20 августа 2010

TimeSpan вообще не имеет опций форматирования до .NET 4.0, вам придется конвертировать его в DateTime через свойство Ticks.Ничто не может быть удаленно закрыто в параметрах форматирования DateTime.String (формат), однако вам придется написать это самостоятельно.

В .NET 4.0 TimeSpan получил переопределение ToString (формат).Пользовательские строки форматирования описаны здесь .Ваше третье требование будет нуждаться в коде.

5 голосов
/ 20 августа 2010

В .NET 3.5 и более ранних версиях вам нужно написать собственную функцию.

В .NET 4 добавлена ​​поддержка форматирования TimeSpan, подробности см. TimeSpan.ToString(string).

3 голосов
/ 20 августа 2010

Нет встроенного способа выполнить ваше требование, по крайней мере, в .NET 3.5.Вот класс, расширяющий TimeSpan для обеспечения желаемой функциональности.

public static class TimeSpanEx
{
    public static string FormattedString(this TimeSpan ts)
    {
        int days = (int)ts.TotalDays;
        int hrs = (int)ts.Hours;
        int mins = (int)ts.Minutes;
        StringBuilder sb = new StringBuilder();

        if (days > 0)
        {
            sb.Append(days.ToString() + (days == 1 ? " day, " : " days, "));
        }

        if (hrs > 0 || days > 0)
        {
            sb.Append(hrs.ToString() + (hrs == 1 ? " hour, " : " hours, "));
        }

        sb.Append(mins.ToString() + (mins == 1 ? " min" : " mins"));

        return sb.ToString();
    }
}
2 голосов
/ 20 августа 2010

К сожалению, в .Net нет ничего доступного напрямую.Для себя я решил проблему следующим образом:

public static class TimeSpanExtensions
{
    public static string ToDetailedString(this TimeSpan timeSpan)
    {
        if (timeSpan == null)
            throw new ArgumentNullException("timeSpan");

        var sb = new StringBuilder(30);

        var current = timeSpan.ToDaysString();

        if (!String.IsNullOrEmpty(current))
            sb.Append(current);

        current = timeSpan.ToHoursString();

        if (!String.IsNullOrEmpty(current))
        {
            if (sb.Length > 0)
                sb.Append(" ");

            sb.Append(current);
        }

        current = timeSpan.ToMinutesString();

        if (!String.IsNullOrEmpty(current))
        {
            if (sb.Length > 0)
                sb.Append(" ");

            sb.Append(current);
        }

        return sb.ToString();
    }

    public static string ToDaysString(this TimeSpan timeSpan)
    {
        if (timeSpan == null)
            throw new ArgumentNullException("timeSpan");

        int days = (int)timeSpan.TotalDays;

        switch (days)
        {
            case 0:
                return String.Empty;
            case 1:
                return "1 day";
            default:
                return days + " days";
        }
    }

    public static string ToHoursString(this TimeSpan timeSpan)
    {
        if (timeSpan == null)
            throw new ArgumentNullException("timeSpan");

        switch (timeSpan.Hours)
        {
            case 0:
                return String.Empty;
            case 1:
                return "1 hour";
            default:
                return timeSpan.Hours + " hours";
        }
    }

    public static string ToMinutesString(this TimeSpan timeSpan)
    {
        if (timeSpan == null)
            throw new ArgumentNullException("timeSpan");

        switch (timeSpan.Minutes)
        {
            case 0:
                return String.Empty;
            case 1:
                return "1 minute";
            default:
                return timeSpan.Minutes + " minutes";
        }
    }
}

Возможно, это не самое элегантное решение, и я думаю, что можно сделать некоторые улучшения, особенно в функции ToDetailedString(), но она работает абсолютно нормально.1005 *

...