c# - valor - ¿Cómo convierto un TimeSpan a una cadena formateada?
timespan c# ejemplos (14)
¿ 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
.
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo puedo String.Format un objeto TimeSpan con un formato personalizado en .NET? 18 respuestas
- Formato del tiempo [duplicado] 5 respuestas
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
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");
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"
Esta es la solución más corta.
timeSpan.ToString(@"hh/:mm");
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;
}
}
}
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
.
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 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.
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");
}
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);
}
}
}
public static class TimeSpanFormattingExtensions
{
public static string ToReadableString(this TimeSpan span)
{
return string.Join(", ", span.GetReadableStringElements()
.Where(str => !string.IsNullOrWhiteSpace(str)));
}
private static IEnumerable<string> 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);
}
}
'''''' <summary>
'''''' 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).
'''''' </summary>
'''''' <param name="NumDbl"></param>
'''''' <param name="SglUnitStr"></param>
'''''' <param name="PluralUnitStr"></param>
'''''' <param name="FormatStr"></param>
'''''' <param name="FmtProvider"></param>
'''''' <returns></returns>
'''''' <remarks></remarks>
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
'''''' <summary>
'''''' Info about a # Unit.
'''''' </summary>
'''''' <remarks></remarks>
Public Class clsNumUnitInfoItem
'''''' <summary>
'''''' Name of a Singular Unit (i.e. "day", "trillion", "foot")
'''''' </summary>
'''''' <remarks></remarks>
Public UnitSglStr As String
'''''' <summary>
'''''' Name of a Plural Unit (i.e. "days", "trillion", "feet")
'''''' </summary>
'''''' <remarks></remarks>
Public UnitPluralStr As String
'''''' <summary>
'''''' # of Units to = 1 of Next Higher (aka Parent) Unit (i.e. 24 "hours", 1000 "million",
'''''' 5280 "feet")
'''''' </summary>
'''''' <remarks></remarks>
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
'''''' <summary>
'''''' Convert a specified Double Number (NumDbl) to a long (aka verbose) format (i.e. "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.
'''''' </summary>
'''''' <param name="NumDbl"></param>
'''''' <param name="NumUnitInfoItms"></param>
'''''' <param name="ConjStr"></param>
'''''' <param name="MinUnitLevInt"></param>
'''''' <param name="MaxUnitLevInt"></param>
'''''' <param name="MaxNumUnitLevsInt"></param>
'''''' <param name="RoundUpBool"></param>
'''''' <param name="FormatStr"></param>
'''''' <param name="FmtProvider"></param>
'''''' <returns></returns>
'''''' <remarks></remarks>
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
'''''' <summary>
'''''' Call NumToLongStr with a specified TimeSpan''s (TS) TotalDays.
'''''' </summary>
'''''' <param name="TS"></param>
'''''' <param name="TimeUnitInfoItms"></param>
'''''' <param name="ConjStr"></param>
'''''' <param name="MinUnitLevInt"></param>
'''''' <param name="MaxUnitLevInt"></param>
'''''' <param name="MaxNumUnitLevsInt"></param>
'''''' <param name="RoundUpBool"></param>
'''''' <param name="FormatStr"></param>
'''''' <param name="FmtProvider"></param>
'''''' <returns></returns>
'''''' <remarks></remarks>
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
'''''' <summary>
'''''' Call TimeSpanToStr with TimeLongEnUnitInfoItms.
'''''' </summary>
'''''' <param name="TS"></param>
'''''' <param name="MinUnitLevInt"></param>
'''''' <param name="MaxUnitLevInt"></param>
'''''' <param name="MaxNumUnitLevsInt"></param>
'''''' <param name="RoundUpBool"></param>
'''''' <param name="FormatStr"></param>
'''''' <param name="FmtProvider"></param>
'''''' <returns></returns>
'''''' <remarks></remarks>
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