Как я могу String.Format объект TimeSpan с пользовательским форматом в .NET?

Каков рекомендуемый способ форматирования объектов TimeSpan в строку с пользовательским форматом?

Ответ 1

Обратите внимание: этот ответ предназначен для .Net 4.0 и выше. Если вы хотите отформатировать TimeSpan в .Net 3.5 или ниже, см. ответ JohannesH.

Пользовательские строки формата TimeSpan были введены в .Net 4.0. Вы можете найти полную ссылку на спецификаторы доступных форматов на странице MSDN Custom TimeSpan Format Strings.

Здесь приведен пример строки формата времени:

string.Format("{0:hh\\:mm\\:ss}", myTimeSpan); //example output 15:36:15

(UPDATE), и вот пример использования интерполяции строк С# 6:

$"{myTimeSpan:hh\\:mm\\:ss}"; //example output 15:36:15

Вам нужно избежать символа ":" с "\" (который сам должен быть экранирован, если вы не используете строку в виде строки).

В этой выдержке из страницы MSDN Custom TimeSpan Format Strings рассказывается об экранировании ":" и ".". символов в строке формата:

Пользовательские спецификации формата TimeSpan не включают символы разделителя заполнителей, такие как символы, которые отделяют дни от часов, часов от минут или секунд от дробных секунд. Вместо этого эти символы должны быть включены в строку пользовательского формата в виде строковых литералов. Например, "dd.hh: mm" определяет период (.) Как разделитель между днями и часами и двоеточие (:) как разделитель между часами и минутами.

Ответ 2

Для.NET 3.5 и ниже вы можете использовать:

string.Format ("{0:00}:{1:00}:{2:00}", 
               (int)myTimeSpan.TotalHours, 
                    myTimeSpan.Minutes, 
                    myTimeSpan.Seconds);

Код, взятый из ответа Джона Скита по байтам

Для.NET 4.0 и выше см. Ответ DoctaJonez.

Ответ 3

Один из способов - создать объект DateTime и использовать его для форматирования:

new DateTime(myTimeSpan.Ticks).ToString(myCustomFormat)

// or using String.Format:
String.Format("{0:HHmmss}", new DateTime(myTimeSpan.Ticks))

Так я знаю. Я надеюсь, что кто-то может предложить лучший способ.

Ответ 4

Просто. Используйте TimeSpan.ToString с c, g или G. Дополнительная информация на MSDN

Ответ 5

Я бы пошел с

myTimeSpan.ToString("hh\\:mm\\:ss");

Ответ 7

Это потрясающе:

string.Format("{0:00}:{1:00}:{2:00}",
               (int)myTimeSpan.TotalHours,
               myTimeSpan.Minutes,
               myTimeSpan.Seconds);

Ответ 8

Лично мне нравится этот подход:

TimeSpan ts = ...;
string.Format("{0:%d}d {0:%h}h {0:%m}m {0:%s}s", ts);

Вы можете сделать это как обычай, как вам нравится, без проблем:

string.Format("{0:%d}days {0:%h}hours {0:%m}min {0:%s}sec", ts);
string.Format("{0:%d}d {0:%h}h {0:%m}' {0:%s}''", ts);

Ответ 9

Вы также можете использовать:

Dim ts As New TimeSpan(35, 21, 59, 59)  '(11, 22, 30, 30)    '
Dim TimeStr1 As String = String.Format("{0:c}", ts)
Dim TimeStr2 As String = New Date(ts.Ticks).ToString("dd.HH:mm:ss")

EDIT:

Вы также можете посмотреть Strings.Format.

    Dim ts As New TimeSpan(23, 30, 59)
    Dim str As String = Strings.Format(New DateTime(ts.Ticks), "H:mm:ss")

Ответ 10

if (timeSpan.TotalDays < 1)
    return timeSpan.ToString(@"hh\:mm\:ss");

return timeSpan.TotalDays < 2
    ? timeSpan.ToString(@"d\ \d\a\y\ hh\:mm\:ss")
    : timeSpan.ToString(@"d\ \d\a\y\s\ hh\:mm\:ss");

Все литералы должны быть экранированы.

Ответ 11

Я использовал код ниже. Он длинный, но все же это одно выражение и производит очень дружественный вывод, поскольку он не выводит дни, часы, минуты или секунды, если они имеют значение нуля.

В образце он выводит результат: "4 дня 1 час 3 секунды".

TimeSpan sp = new TimeSpan(4,1,0,3);
string.Format("{0}{1}{2}{3}", 
        sp.Days > 0 ? ( sp.Days > 1 ? sp.ToString(@"d\ \d\a\y\s\ "): sp.ToString(@"d\ \d\a\y\ ")):string.Empty,
        sp.Hours > 0 ? (sp.Hours > 1 ? sp.ToString(@"h\ \h\o\u\r\s\ ") : sp.ToString(@"h\ \h\o\u\r\ ")):string.Empty,
        sp.Minutes > 0 ? (sp.Minutes > 1 ? sp.ToString(@"m\ \m\i\n\u\t\e\s\ ") :sp.ToString(@"m\ \m\i\n\u\t\e\ ")):string.Empty,
        sp.Seconds > 0 ? (sp.Seconds > 1 ? sp.ToString(@"s\ \s\e\c\o\n\d\s"): sp.ToString(@"s\ \s\e\c\o\n\d\s")):string.Empty);

Ответ 12

Я использую этот метод. Я бельгийский и говорю голландский, поэтому множественное число часов и минут не просто добавляет 's' до конца, но почти другое слово, чем единственное.

Это может показаться длинным, но это очень читаемо, я думаю:

 public static string SpanToReadableTime(TimeSpan span)
    {
        string[] values = new string[4];  //4 slots: days, hours, minutes, seconds
        StringBuilder readableTime = new StringBuilder();

        if (span.Days > 0)
        {
            if (span.Days == 1)
                values[0] = span.Days.ToString() + " dag"; //day
            else
                values[0] = span.Days.ToString() + " dagen";  //days

            readableTime.Append(values[0]);
            readableTime.Append(", ");
        }
        else
            values[0] = String.Empty;


        if (span.Hours > 0)
        {
            if (span.Hours == 1)
                values[1] = span.Hours.ToString() + " uur";  //hour
            else
                values[1] = span.Hours.ToString() + " uren";  //hours

            readableTime.Append(values[1]);
            readableTime.Append(", ");

        }
        else
            values[1] = string.Empty;

        if (span.Minutes > 0)
        {
            if (span.Minutes == 1)
                values[2] = span.Minutes.ToString() + " minuut";  //minute
            else
                values[2] = span.Minutes.ToString() + " minuten";  //minutes

            readableTime.Append(values[2]);
            readableTime.Append(", ");
        }
        else
            values[2] = string.Empty;

        if (span.Seconds > 0)
        {
            if (span.Seconds == 1)
                values[3] = span.Seconds.ToString() + " seconde";  //second
            else
                values[3] = span.Seconds.ToString() + " seconden";  //seconds

            readableTime.Append(values[3]);
        }
        else
            values[3] = string.Empty;


        return readableTime.ToString();
    }//end SpanToReadableTime

Ответ 13

Это подход, который я использовал сам с условным форматированием. и я публикую его здесь, потому что я думаю, что это чистый путь.

$"{time.Days:#0:;;\\}{time.Hours:#0:;;\\}{time.Minutes:00:}{time.Seconds:00}"

пример выходов:

00:00 (минимум)

1:43:04 (когда у нас есть часы)

15:03:01 (когда часы больше 1 цифры)

2:4:22:04 (когда у нас есть дни.)

Форматирование прост. time.Days:#0:;;\\ формат до ;; соответствует значению, когда значение положительное. отрицательные значения игнорируются. и для нулевых значений имеем ;;\\, чтобы скрыть его в форматированной строке. обратите внимание, что экранированная обратная косая черта необходима, иначе она не будет правильно отформатирована.

Ответ 14

Вот мой метод расширения:

public static string ToFormattedString(this TimeSpan ts)
{
    const string separator = ", ";

    if (ts.TotalMilliseconds < 1) { return "No time"; }

    return string.Join(separator, new string[]
    {
        ts.Days > 0 ? ts.Days + (ts.Days > 1 ? " days" : " day") : null,
        ts.Hours > 0 ? ts.Hours + (ts.Hours > 1 ? " hours" : " hour") : null,
        ts.Minutes > 0 ? ts.Minutes + (ts.Minutes > 1 ? " minutes" : " minute") : null,
        ts.Seconds > 0 ? ts.Seconds + (ts.Seconds > 1 ? " seconds" : " second") : null,
        ts.Milliseconds > 0 ? ts.Milliseconds + (ts.Milliseconds > 1 ? " milliseconds" : " millisecond") : null,
    }.Where(t => t != null));
}

Пример вызова:

string time = new TimeSpan(3, 14, 15, 0, 65).ToFormattedString();

Вывод:

3 days, 14 hours, 15 minutes, 65 milliseconds

Ответ 15

Это боль в VS 2010, здесь мое решение для решения проблемы.

 public string DurationString
        {
            get 
            {
                if (this.Duration.TotalHours < 24)
                    return new DateTime(this.Duration.Ticks).ToString("HH:mm");
                else //If duration is more than 24 hours
                {
                    double totalminutes = this.Duration.TotalMinutes;
                    double hours = totalminutes / 60;
                    double minutes = this.Duration.TotalMinutes - (Math.Floor(hours) * 60);
                    string result = string.Format("{0}:{1}", Math.Floor(hours).ToString("00"), Math.Floor(minutes).ToString("00"));
                    return result;
                }
            } 
        }

Ответ 16

Вот моя версия. Он показывает только столько, сколько необходимо, обрабатывает плюрализацию, негативы, и я старался сделать его легким.

Примеры вывода

0 seconds
1.404 seconds
1 hour, 14.4 seconds
14 hours, 57 minutes, 22.473 seconds
1 day, 14 hours, 57 minutes, 22.475 seconds

Код

public static class TimeSpanExtensions
{
    public static string ToReadableString(this TimeSpan timeSpan)
    {
        int days = (int)(timeSpan.Ticks / TimeSpan.TicksPerDay);
        long subDayTicks = timeSpan.Ticks % TimeSpan.TicksPerDay;

        bool isNegative = false;
        if (timeSpan.Ticks < 0L)
        {
            isNegative = true;
            days = -days;
            subDayTicks = -subDayTicks;
        }

        int hours = (int)((subDayTicks / TimeSpan.TicksPerHour) % 24L);
        int minutes = (int)((subDayTicks / TimeSpan.TicksPerMinute) % 60L);
        int seconds = (int)((subDayTicks / TimeSpan.TicksPerSecond) % 60L);
        int subSecondTicks = (int)(subDayTicks % TimeSpan.TicksPerSecond);
        double fractionalSeconds = (double)subSecondTicks / TimeSpan.TicksPerSecond;

        var parts = new List<string>(4);

        if (days > 0)
            parts.Add(string.Format("{0} day{1}", days, days == 1 ? null : "s"));
        if (hours > 0)
            parts.Add(string.Format("{0} hour{1}", hours, hours == 1 ? null : "s"));
        if (minutes > 0)
            parts.Add(string.Format("{0} minute{1}", minutes, minutes == 1 ? null : "s"));
        if (fractionalSeconds.Equals(0D))
        {
            switch (seconds)
            {
                case 0:
                    // Only write "0 seconds" if we haven't written anything at all.
                    if (parts.Count == 0)
                        parts.Add("0 seconds");
                    break;

                case 1:
                    parts.Add("1 second");
                    break;

                default:
                    parts.Add(seconds + " seconds");
                    break;
            }
        }
        else
        {
            parts.Add(string.Format("{0}{1:.###} seconds", seconds, fractionalSeconds));
        }

        string resultString = string.Join(", ", parts);
        return isNegative ? "(negative) " + resultString : resultString;
    }
}

Ответ 17

Если вы хотите, чтобы формат продолжительности был похож на youtube, учитывая количество секунд

int[] duration = { 0, 4, 40, 59, 60, 61, 400, 4000, 40000, 400000 };
foreach (int d in duration)
{
    Console.WriteLine("{0, 6} -> {1, 10}", d, d > 59 ? TimeSpan.FromSeconds(d).ToString().TrimStart("00:".ToCharArray()) : string.Format("0:{0:00}", d));
}

Вывод:

     0 ->       0:00
     4 ->       0:04
    40 ->       0:40
    59 ->       0:59
    60 ->       1:00
    61 ->       1:01
   400 ->       6:40
  4000 ->    1:06:40
 40000 ->   11:06:40
400000 -> 4.15:06:40

Ответ 18

Я хотел вернуть строку, такую ​​как "1 день 2 часа 3 минуты", а также принять во внимание, если, например, дни или минуты равны 0, а затем не отображаются. благодаря John Rasch за его ответ, который мой едва расширяет

TimeSpan timeLeft = New Timespan(0, 70, 0);
String.Format("{0}{1}{2}{3}{4}{5}",
    Math.Floor(timeLeft.TotalDays) == 0 ? "" : 
    Math.Floor(timeLeft.TotalDays).ToString() + " ",
    Math.Floor(timeLeft.TotalDays) == 0 ? "" : Math.Floor(timeLeft.TotalDays) == 1 ? "day " : "days ",
    timeLeft.Hours == 0 ? "" : timeLeft.Hours.ToString() + " ",
    timeLeft.Hours == 0 ? "" : timeLeft.Hours == 1 ? "hour " : "hours ",
    timeLeft.Minutes == 0 ? "" : timeLeft.Minutes.ToString() + " ",
    timeLeft.Minutes == 0 ? "" : timeLeft.Minutes == 1 ? "minute " : "minutes ");

Ответ 19

Метод Substring отлично работает, когда вам нужны только часы: минуты: секунды. Это простой, чистый код и легкий для понимания.

    var yourTimeSpan = DateTime.Now - DateTime.Now.AddMinutes(-2);

    var formatted = yourTimeSpan.ToString().Substring(0,8);// 00:00:00 

    Console.WriteLine(formatted);