Comment convertir un TimeSpan en une chaîne formatée? [dupliquer]
Question
Cette question a déjà une réponse ici:
J'ai deux vars DateTime, beginTime et endTime. J'ai compris la différence en procédant comme suit:
TimeSpan dateDifference = endTime.Subtract(beginTime);
Comment puis-je maintenant renvoyer une chaîne de ce type au format hh heures, mm minutes, ss secondes à l'aide de C #.
Si la différence était de 00: 06: 32.4458750
Il devrait retourner ce 00 heures, 06 minutes, 32 secondes
La solution
TimeSpan.ToString () ferait l'affaire pour vous? Sinon, il semble que l'exemple de code de cette page explique comment formater un objet TimeSpan
sur mesure.
Autres conseils
Je viens de construire quelques méthodes d'extension TimeSpan. Je pensais pouvoir partager:
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;
}
En le convertissant en date / heure, vous pouvez obtenir les formats localisés:
new DateTime(timeSpan.Ticks).ToString("HH:mm");
C’est la solution la plus courte.
timeSpan.ToString(@"hh\:mm");
Utilisez String.Format () avec plusieurs paramètres.
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);
}
}
}
Le moyen le plus simple de formater un TimeSpan
consiste à l'ajouter à un DateTime
et à formater celui-ci:
string formatted = (DateTime.Today + dateDifference).ToString("HH 'hrs' mm 'mins' ss 'secs'");
Ceci fonctionne tant que le décalage horaire ne dépasse pas 24 heures.
La propriété Today
renvoie une <=> valeur où le composant heure est égal à zéro, le composant heure du résultat est donc la <=> valeur.
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);
}
}
Selon la documentation Microsoft , la structure TimeSpan expose les heures, les minutes, les secondes et les millisecondes en tant que membres entiers. Peut-être que vous voulez quelque chose comme:
dateDifference.Hours.ToString() + " hrs, " + dateDifference.Minutes.ToString() + " mins, " + dateDifference.Seconds.ToString() + " secs"
Vous pouvez utiliser le code suivant.
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);
}
}
Merci à Peter pour la méthode d'extension. Je l'ai modifié pour fonctionner avec des durées plus longues:
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;
}
}
}
Je sais que cette question est ancienne, mais .Net 4 prend désormais en charge TimeSpan personnalisé. formats .
Je sais aussi que cela a été mentionné, mais cela m’a pris au dépourvu. Convertir Ticks en DateTime fonctionne, mais ne gère pas correctement plus de 24 heures.
new DateTime((DateTime.Now - DateTime.Now.AddHours(-25)).Ticks).ToString("HH:mm")
Cela vous mènera à 01h00 et non à 25h00 comme vous pouvez vous attendre.
J'ai également eu un problème similaire et j'ai créé ma propre extension, mais il semble être un peu différent de tout le reste.
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");
}
Je sais que c'est une réponse tardive, mais cela fonctionne pour moi:
TimeSpan dateDifference = new TimeSpan(0,0,0, (int)endTime.Subtract(beginTime).TotalSeconds);
dateDifference devrait maintenant exclure les parties inférieures à une seconde. Fonctionne également en .net 2.0.
''' <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