Wie kann ich String.Format ein TimeSpan-Objekt mit einem benutzerdefinierten Format in .NET?

Was ist die empfohlene Methode zum Formatieren von TimeSpan Objekten in eine Zeichenfolge mit einem benutzerdefinierten Format?

Bitte beachten Sie: Diese Antwort ist für .Net 4.0 und höher. Wenn Sie TimeSpan in .Net 3.5 oder niedriger formatieren möchten, lesen Sie bitte JohannesHs Antwort .

Benutzerdefinierte TimeSpan-Formatzeichenfolgen wurden in .NET 4.0 eingeführt. Eine vollständige Referenz der verfügbaren Formatbezeichner finden Sie auf der Seite MSDN Custom TimeSpan Format Strings .

Hier ist eine Beispiel-Timespan-Formatzeichenfolge:

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

( UPDATE ) und hier ist ein Beispiel mit C # 6 String-Interpolation:

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

Sie müssen das Zeichen “:” mit einem “\” (das selbst mit einem Escape-Zeichen versehen werden muss, wenn Sie eine Verbatim-Zeichenfolge verwenden) umgehen.

Dieser Auszug aus der MSDN Custom TimeSpan Format Strings- Seite erläutert das Entweichen der “:” und “.” Zeichen in einer Formatzeichenfolge:

Die benutzerdefinierten TimeSpan-Formatbezeichner enthalten keine Platzhaltertrennzeichen, z. B. die Symbole, die Tage von Stunden, Stunden von Minuten oder Sekunden von Sekundenbruchteilen trennen. Stattdessen müssen diese Symbole in der benutzerdefinierten Formatzeichenfolge als Zeichenfolgenliterale enthalten sein. Zum Beispiel definiert “dd.hh: mm” einen Punkt (.) Als Trennzeichen zwischen Tagen und Stunden und einen Doppelpunkt (:) als Trennzeichen zwischen Stunden und Minuten.

Für .NET 3.5 und niedriger könnten Sie verwenden:

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

Code aus einer Jon Skeet Antwort auf Bytes

Für .NET 4.0 und höher, siehe DoctaJonez- Antwort .

Eine Möglichkeit besteht darin, ein DateTime Objekt zu erstellen und es für die Formatierung zu verwenden:

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

So weiß ich es. Ich hoffe, dass jemand einen besseren Weg vorschlagen kann.

Einfach. Verwenden Sie TimeSpan.ToString mit c, g oder G. Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/ee372286.aspx

 Dim duration As New TimeSpan(1, 12, 23, 62) DEBUG.WriteLine("Time of Travel: " + duration.ToString("dd\.hh\:mm\:ss")) 

Es funktioniert für Framework 4

http://msdn.microsoft.com/en-us/library/ee372287.aspx

Persönlich mag ich diesen Ansatz:

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

Sie können dies so benutzerdefiniert wie Sie möchten ohne Probleme:

 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); 

Ich würde mitgehen

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

Das ist großartig:

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

Sie können auch gehen mit:

 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") 

BEARBEITEN:

Sie können auch Strings.Format betrachten .

  Dim ts As New TimeSpan(23, 30, 59) Dim str As String = Strings.Format(New DateTime(ts.Ticks), "H:mm:ss") 
 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"); 

Alle literalen Zeichen müssen mit Escapezeichen versehen sein.

Ich habe den folgenden Code verwendet. Es ist lang, aber immer noch ein Ausdruck und erzeugt eine sehr freundliche Ausgabe, da es keine Tage, Stunden, Minuten oder Sekunden ausgibt, wenn sie den Wert Null haben.

In der Probe produziert es Ausgabe: “4 Tage 1 Stunde 3 Sekunden”.

 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); 

Ich benutze diese Methode. Ich bin Belgier und spreche Holländer, so dass Plural von Stunden und Minuten nicht nur “s” zum Ende, sondern fast ein anderes Wort als singular hinzufügt.

Es mag lange scheinen, aber es ist sehr lesenswert, denke ich:

  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 

Dies ist ein Problem in VS 2010, hier ist meine Lösung für die Problemumgehung.

  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; } } } 

Dies ist der Ansatz, den ich selbst mit bedingter Formatierung verwendet habe. und ich poste es hier, weil ich denke, dass das ein sauberer Weg ist.

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

Beispiel für Ausgänge:

00:00 (Minimum)

1:43:04 (wenn wir Stunden haben)

15:03:01 (wenn Stunden mehr als 1 Ziffer sind)

2:4:22:04 (wenn wir Tage haben.)

Die Formatierung ist einfach. time.Days:#0:;;\\ das Format vor ;; ist, wenn der Wert positiv ist. negative Werte werden ignoriert. und für Nullwerte haben wir ;;\\ , um es in formatierter Zeichenkette zu verstecken. Beachten Sie, dass der Escaped-Backslash erforderlich ist, andernfalls wird er nicht korrekt formatiert.

Hier ist meine Version. Es zeigt nur so viel wie nötig, behandelt Pluralisierung, Negative und ich habe versucht, es leicht zu machen.

Ausgabebeispiele

 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 

Code

 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(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; } } 

Wenn Sie möchten, dass das Dauerformat youtube ähnlich ist, geben Sie die Anzahl der Sekunden an

 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)); } 

Ausgabe:

  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 

Ich wollte eine Zeichenfolge wie “1 Tag 2 Stunden 3 Minuten” zurückgeben und auch berücksichtigen, ob zB Tage oder Minuten 0 sind und dann nicht angezeigt werden. Vielen Dank an John Rasch für seine Antwort, welche meiner ist kaum eine Erweiterung von

 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 "); 

Hier ist meine Erweiterungsmethode :

 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)); } 

Beispiel Aufruf:

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

Ausgabe:

 3 days, 14 hours, 15 minutes, 65 milliseconds