¿Cómo convierto un TimeSpan a una cadena formateada?

Tengo dos DateTime vars, beginTime y endTime. He obtenido la diferencia de ellos haciendo lo siguiente:

TimeSpan dateDifference = endTime.Subtract(beginTime); 

¿Cómo puedo ahora devolver una cadena de esto en formato hh hrs, mm mins, ss secs usando C #.

Si la diferencia fue 00: 06: 32.4458750

Debería devolver este 00 horas, 06 minutos, 32 segundos

¿ TimeSpan.ToString () haría el truco para usted? Si no, parece que el ejemplo de código en esa página describe cómo hacer un formateo personalizado de un objeto TimeSpan .

Acabo de construir algunos métodos de extensión TimeSpan. Pensé que podría compartir:

 public static string ToReadableAgeString(this TimeSpan span) { return string.Format("{0:0}", span.Days / 365.25); } public static string ToReadableString(this TimeSpan span) { string formatted = string.Format("{0}{1}{2}{3}", span.Duration().Days > 0 ? string.Format("{0:0} day{1}, ", span.Days, span.Days == 1 ? String.Empty : "s") : string.Empty, span.Duration().Hours > 0 ? string.Format("{0:0} hour{1}, ", span.Hours, span.Hours == 1 ? String.Empty : "s") : string.Empty, span.Duration().Minutes > 0 ? string.Format("{0:0} minute{1}, ", span.Minutes, span.Minutes == 1 ? String.Empty : "s") : string.Empty, span.Duration().Seconds > 0 ? string.Format("{0:0} second{1}", span.Seconds, span.Seconds == 1 ? String.Empty : "s") : string.Empty); if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2); if (string.IsNullOrEmpty(formatted)) formatted = "0 seconds"; return formatted; } 

Al convertirlo a una fecha y hora, puede obtener formatos localizados:

 new DateTime(timeSpan.Ticks).ToString("HH:mm"); 

Esta es la solución más corta.

 timeSpan.ToString(@"hh\:mm"); 

Use String.Format () con múltiples parámetros.

 using System; namespace TimeSpanFormat { class Program { static void Main(string[] args) { TimeSpan dateDifference = new TimeSpan(0, 0, 6, 32, 445); string formattedTimeSpan = string.Format("{0:D2} hrs, {1:D2} mins, {2:D2} secs", dateDifference.Hours, dateDifference.Minutes, dateDifference.Seconds); Console.WriteLine(formattedTimeSpan); } } } 

La forma más fácil de formatear un TimeSpan es agregarlo a un DateTime y formatear eso:

 string formatted = (DateTime.Today + dateDifference).ToString("HH 'hrs' mm 'mins' ss 'secs'"); 

Esto funciona siempre que la diferencia de tiempo no sea más de 24 horas.

La propiedad Today devuelve un valor de DateTime donde el componente de tiempo es cero, por lo que el componente de tiempo del resultado es el valor de TimeSpan .

  public static class TimeSpanFormattingExtensions { public static string ToReadableString(this TimeSpan span) { return string.Join(", ", span.GetReadableStringElements() .Where(str => !string.IsNullOrWhiteSpace(str))); } private static IEnumerable GetReadableStringElements(this TimeSpan span) { yield return GetDaysString((int)Math.Floor(span.TotalDays)); yield return GetHoursString(span.Hours); yield return GetMinutesString(span.Minutes); yield return GetSecondsString(span.Seconds); } private static string GetDaysString(int days) { if (days == 0) return string.Empty; if (days == 1) return "1 day"; return string.Format("{0:0} days", days); } private static string GetHoursString(int hours) { if (hours == 0) return string.Empty; if (hours == 1) return "1 hour"; return string.Format("{0:0} hours", hours); } private static string GetMinutesString(int minutes) { if (minutes == 0) return string.Empty; if (minutes == 1) return "1 minute"; return string.Format("{0:0} minutes", minutes); } private static string GetSecondsString(int seconds) { if (seconds == 0) return string.Empty; if (seconds == 1) return "1 second"; return string.Format("{0:0} seconds", seconds); } } 

De acuerdo con la documentación de Microsoft , la estructura TimeSpan expone horas, minutos, segundos y milisegundos como miembros enteros. Tal vez quieras algo como:

 dateDifference.Hours.ToString() + " hrs, " + dateDifference.Minutes.ToString() + " mins, " + dateDifference.Seconds.ToString() + " secs" 

Gracias a Peter por el método de extensión. Lo modifiqué para que funcione mejor por períodos de tiempo más largos:

 namespace ExtensionMethods { public static class TimeSpanExtensionMethods { public static string ToReadableString(this TimeSpan span) { string formatted = string.Format("{0}{1}{2}", (span.Days / 7) > 0 ? string.Format("{0:0} weeks, ", span.Days / 7) : string.Empty, span.Days % 7 > 0 ? string.Format("{0:0} days, ", span.Days % 7) : string.Empty, span.Hours > 0 ? string.Format("{0:0} hours, ", span.Hours) : string.Empty); if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2); return formatted; } } } 

Puedes usar el siguiente código.

 public static class TimeSpanExtensions { public static String Verbose(this TimeSpan timeSpan) { var hours = timeSpan.Hours; var minutes = timeSpan.Minutes; if (hours > 0) return String.Format("{0} hours {1} minutes", hours, minutes); return String.Format("{0} minutes", minutes); } } 

Sé que esta pregunta es anterior, pero .Net 4 ahora es compatible con los formatos TimeSpan personalizados .

También sé que se ha mencionado pero me sorprendió, convirtiendo Ticks en DateTime pero no maneja adecuadamente más de 24 horas.

 new DateTime((DateTime.Now - DateTime.Now.AddHours(-25)).Ticks).ToString("HH:mm") 

Eso te conseguirá 01:00 a 25:00 como es de esperar.

También tuve un problema similar y creé mi propia extensión, pero parece ser un poco diferente a todo lo demás.

  public static string TimeSpanToString(this TimeSpan timeSpan) { //if it's negative if (timeSpan.Ticks < 0) { timeSpan = timeSpan - timeSpan - timeSpan; if (timeSpan.Days != 0) return string.Format("-{0}:{1}", timeSpan.Days.ToString("d"), new DateTime(timeSpan.Ticks).ToString("HH:mm:ss")); else return new DateTime(timeSpan.Ticks).ToString("-HH:mm:ss"); } //if it has days else if (timeSpan.Days != 0) return string.Format("{0}:{1}", timeSpan.Days.ToString("d"), new DateTime(timeSpan.Ticks).ToString("HH:mm:ss")); //otherwise return the time else return new DateTime(timeSpan.Ticks).ToString("HH:mm:ss"); } 

Sé que esta es una respuesta tardía, pero esto funciona para mí:

 TimeSpan dateDifference = new TimeSpan(0,0,0, (int)endTime.Subtract(beginTime).TotalSeconds); 

dateDifference ahora debe excluir las partes más pequeñas que un segundo. Funciona en .NET 2.0 también.

 '''  ''' Return specified Double # (NumDbl) as String using specified Number Format String (FormatStr, ''' Default = "N0") and Format Provider (FmtProvider, Default = Nothing) followed by space and, ''' if NumDbl = 1, the specified Singular Unit Name (SglUnitStr), else the Plural Unit Name ''' (PluralUnitStr). '''  '''  '''  '''  '''  '''  '''  '''  Public Function PluralizeUnitsStr( _ ByVal NumDbl As Double, _ ByVal SglUnitStr As String, _ ByVal PluralUnitStr As String, _ Optional ByVal FormatStr As String = "N0", _ Optional ByVal FmtProvider As System.IFormatProvider = Nothing _ ) As String PluralizeUnitsStr = NumDbl.ToString(FormatStr, FmtProvider) & " " Dim RsltUnitStr As String If NumDbl = 1 Then RsltUnitStr = SglUnitStr Else RsltUnitStr = PluralUnitStr End If PluralizeUnitsStr &= RsltUnitStr End Function '''  ''' Info about a # Unit. '''  '''  Public Class clsNumUnitInfoItem '''  ''' Name of a Singular Unit (ie "day", "trillion", "foot") '''  '''  Public UnitSglStr As String '''  ''' Name of a Plural Unit (ie "days", "trillion", "feet") '''  '''  Public UnitPluralStr As String '''  ''' # of Units to = 1 of Next Higher (aka Parent) Unit (ie 24 "hours", 1000 "million", ''' 5280 "feet") '''  '''  Public UnitsInParentInt As Integer End Class ' -- clsNumUnitInfoItem Dim TimeLongEnUnitInfoItms As clsNumUnitInfoItem() = { _ New clsNumUnitInfoItem With {.UnitSglStr = "day", .UnitPluralStr = "days", .UnitsInParentInt = 1}, _ New clsNumUnitInfoItem With {.UnitSglStr = "hour", .UnitPluralStr = "hours", .UnitsInParentInt = 24}, _ New clsNumUnitInfoItem With {.UnitSglStr = "minute", .UnitPluralStr = "minutes", .UnitsInParentInt = 60}, _ New clsNumUnitInfoItem With {.UnitSglStr = "second", .UnitPluralStr = "seconds", .UnitsInParentInt = 60}, _ New clsNumUnitInfoItem With {.UnitSglStr = "millisecond", .UnitPluralStr = "milliseconds", .UnitsInParentInt = 1000} _ } ' -- Dim TimeLongEnUnitInfoItms Dim TimeShortEnUnitInfoItms As clsNumUnitInfoItem() = { _ New clsNumUnitInfoItem With {.UnitSglStr = "day", .UnitPluralStr = "days", .UnitsInParentInt = 1}, _ New clsNumUnitInfoItem With {.UnitSglStr = "hr", .UnitPluralStr = "hrs", .UnitsInParentInt = 24}, _ New clsNumUnitInfoItem With {.UnitSglStr = "min", .UnitPluralStr = "mins", .UnitsInParentInt = 60}, _ New clsNumUnitInfoItem With {.UnitSglStr = "sec", .UnitPluralStr = "secs", .UnitsInParentInt = 60}, _ New clsNumUnitInfoItem With {.UnitSglStr = "msec", .UnitPluralStr = "msecs", .UnitsInParentInt = 1000} _ } ' -- Dim TimeShortEnUnitInfoItms '''  ''' Convert a specified Double Number (NumDbl) to a long (aka verbose) format (ie "1 day, ''' 2 hours, 3 minutes, 4 seconds and 567 milliseconds") with a specified Array of Time Unit ''' Info Items (TimeUnitInfoItms), Conjunction (ConjStr, Default = "and"), Minimum Unit Level ''' Shown (MinUnitLevInt) (0 to TimeUnitInfoItms.Length - 1, -1=All), Maximum Unit Level Shown ''' (MaxUnitLevInt) (-1=All), Maximum # of Unit Levels Shown (MaxNumUnitLevsInt) (1 to 0 to ''' TimeUnitInfoItms.Length - 1, 0=All) and Round Last Shown Units Up Flag (RoundUpBool). ''' Suppress leading 0 Unit Levels. '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  Public Function NumToLongStr( _ ByVal NumDbl As Double, _ ByVal NumUnitInfoItms As clsNumUnitInfoItem(), _ Optional ByVal ConjStr As String = "and", _ Optional ByVal MinUnitLevInt As Integer = -1, _ Optional ByVal MaxUnitLevInt As Integer = -1, _ Optional ByVal MaxNumUnitLevsInt As Integer = 0, _ Optional ByVal RoundUpBool As Boolean = False, _ Optional ByVal FormatStr As String = "N0", _ Optional ByVal FmtProvider As System.IFormatProvider = Nothing _ ) As String NumToLongStr = "" Const TUnitDelimStr As String = ", " If (MinUnitLevInt < -1) OrElse (MinUnitLevInt >= NumUnitInfoItms.Length) Then Throw New Exception("Invalid MinUnitLevInt: " & MaxUnitLevInt) End If If (MaxUnitLevInt < -1) OrElse (MaxUnitLevInt >= NumUnitInfoItms.Length) Then Throw New Exception("Invalid MaxDetailLevelInt: " & MaxUnitLevInt) End If If (MaxNumUnitLevsInt < 0) OrElse (MaxNumUnitLevsInt > NumUnitInfoItms.Length) Then Throw New Exception("Invalid MaxNumUnitLevsInt: " & MaxNumUnitLevsInt) End If Dim PrevNumUnitsDbl As Double = NumDbl Dim CurrUnitLevInt As Integer = -1 Dim NumUnitLevsShownInt As Integer = 0 For Each UnitInfoItem In NumUnitInfoItms CurrUnitLevInt += 1 With UnitInfoItem Dim CurrNumUnitsDbl As Double = PrevNumUnitsDbl * .UnitsInParentInt Dim CurrTruncNumUnitsInt As Integer = Math.Truncate(CurrNumUnitsDbl) PrevNumUnitsDbl = CurrNumUnitsDbl If CurrUnitLevInt < MinUnitLevInt Then Continue For PrevNumUnitsDbl -= CurrTruncNumUnitsInt 'If (CurrUnitLevInt > TimeUnitInfoItms.Length) _ ' OrElse _ ' ( _ ' (CurrUnitLevInt > MaxUnitLevInt) AndAlso _ ' (MaxUnitLevInt <> -1) _ ' ) _ ' OrElse _ ' ( _ ' (NumUnitLevsShownInt + 1 > MaxNumUnitLevsInt) AndAlso _ ' (MaxNumUnitLevsInt <> 0) _ ' ) Then Exit For If (CurrUnitLevInt = (NumUnitInfoItms.Length - 1)) OrElse _ (CurrUnitLevInt = MaxUnitLevInt) OrElse _ ((NumUnitLevsShownInt + 1) = MaxNumUnitLevsInt) Then If NumUnitLevsShownInt > 0 Then Dim TUnitDelimStrLenInt As Integer = TUnitDelimStr.Length NumToLongStr = NumToLongStr.Remove( _ NumToLongStr.Length - TUnitDelimStrLenInt, _ TUnitDelimStrLenInt) NumToLongStr &= " " & ConjStr & " " End If Dim CurrNunUnitsRoundedInt As Integer If RoundUpBool Then If CurrNumUnitsDbl <> CurrTruncNumUnitsInt Then CurrNunUnitsRoundedInt = CurrTruncNumUnitsInt + 1 Else CurrNunUnitsRoundedInt = CurrTruncNumUnitsInt End If Else CurrNunUnitsRoundedInt = Math.Round( _ value:=CurrNumUnitsDbl, mode:=MidpointRounding.AwayFromZero) End If NumToLongStr &= _ PluralizeUnitsStr(CurrNunUnitsRoundedInt, _ .UnitSglStr, .UnitPluralStr, FormatStr, FmtProvider) Exit For Else ' -- Not (MaxUnitLevInt or MaxNumUnitLevsInt) If NumUnitLevsShownInt > 0 OrElse CurrTruncNumUnitsInt <> 0 Then NumToLongStr &= _ PluralizeUnitsStr(CurrTruncNumUnitsInt, _ .UnitSglStr, .UnitPluralStr, FormatStr, FmtProvider) & _ TUnitDelimStr NumUnitLevsShownInt += 1 End If End If ' -- Else Not (MaxUnitLevInt or MaxNumUnitLevsInt) End With ' -- UnitInfoItem Next UnitInfoItem End Function '''  ''' Call NumToLongStr with a specified TimeSpan's (TS) TotalDays. '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  Public Function TimeSpanToStr( _ ByVal TS As TimeSpan, _ ByVal TimeUnitInfoItms As clsNumUnitInfoItem(), _ Optional ByVal ConjStr As String = "and", _ Optional ByVal MinUnitLevInt As Integer = -1, _ Optional ByVal MaxUnitLevInt As Integer = -1, _ Optional ByVal MaxNumUnitLevsInt As Integer = 0, _ Optional ByVal RoundUpBool As Boolean = False, _ Optional ByVal FormatStr As String = "N0", _ Optional ByVal FmtProvider As System.IFormatProvider = Nothing _ ) As String Return NumToLongStr( _ NumDbl:=TS.TotalDays, _ NumUnitInfoItms:=TimeUnitInfoItms, _ ConjStr:=ConjStr, _ MinUnitLevInt:=MinUnitLevInt, _ MaxUnitLevInt:=MaxUnitLevInt, _ MaxNumUnitLevsInt:=MaxNumUnitLevsInt, _ RoundUpBool:=RoundUpBool, _ FormatStr:=FormatStr, _ FmtProvider:=FmtProvider _ ) End Function '''  ''' Call TimeSpanToStr with TimeLongEnUnitInfoItms. '''  '''  '''  '''  '''  '''  '''  '''  '''  '''  Public Function TimeSpanToLongEnStr( _ ByVal TS As TimeSpan, _ Optional ByVal MinUnitLevInt As Integer = -1, _ Optional ByVal MaxUnitLevInt As Integer = -1, _ Optional ByVal MaxNumUnitLevsInt As Integer = 0, _ Optional ByVal RoundUpBool As Boolean = False, _ Optional ByVal FormatStr As String = "N0", _ Optional ByVal FmtProvider As System.IFormatProvider = Nothing _ ) As String Return TimeSpanToStr( _ TS:=TS, _ TimeUnitInfoItms:=TimeLongEnUnitInfoItms, _ MinUnitLevInt:=MinUnitLevInt, _ MaxUnitLevInt:=MaxUnitLevInt, _ MaxNumUnitLevsInt:=MaxNumUnitLevsInt, _ RoundUpBool:=RoundUpBool, _ FormatStr:=FormatStr, _ FmtProvider:=FmtProvider _ ) End Function