如何将TimeSpan转换为格式化字符串?(复制)

时间:2021-10-07 08:27:58

This question already has an answer here:

这个问题已经有了答案:

I have two DateTime vars, beginTime and endTime. I have gotten the difference of them by doing the following:

我有两个DateTime vars,起始时间和结束时间。我通过做以下事情得到了他们的不同:

TimeSpan dateDifference = endTime.Subtract(beginTime);

How can I now return a string of this in hh hrs, mm mins, ss secs format using C#.

我现在如何返回一个字符串在hh hrs, mm分钟,ss secs格式使用c#。

If the difference was 00:06:32.4458750

如果区别是00:06:32.4458750。

It should return this 00 hrs, 06 mins, 32 secs

它应该返回00小时,06分钟,32秒

14 个解决方案

#1


36  

Would TimeSpan.ToString() do the trick for you? If not, it looks like the code sample on that page describes how to do custom formatting of a TimeSpan object.

TimeSpan.ToString()能帮你吗?如果不是,则该页面上的代码示例将描述如何执行TimeSpan对象的自定义格式。

#2


158  

I just built a few TimeSpan Extension methods. Thought I could share:

我刚刚构建了一些TimeSpan扩展方法。以为我可以分享:

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

#3


111  

By converting it to a datetime, you can get localized formats:

通过将它转换为datetime,您可以得到本地化的格式:

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

#4


79  

This is the shortest solution.

这是最短的解。

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

#5


30  

Use String.Format() with multiple parameters.

使用String.Format()具有多个参数。

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

#6


8  

The easiest way to format a TimeSpan is to add it to a DateTime and format that:

格式化TimeSpan最简单的方法是将它添加到DateTime中,并将其格式化:

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

This works as long as the time difference is not more than 24 hours.

只要时差不超过24小时就可以。

The Today property returns a DateTime value where the time component is zero, so the time component of the result is the TimeSpan value.

今天的属性返回一个DateTime值,其中时间组件为零,因此结果的时间组件是TimeSpan值。

#7


8  

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

#8


5  

According to the Microsoft documentation, the TimeSpan structure exposes Hours, Minutes, Seconds, and Milliseconds as integer members. Maybe you want something like:

根据Microsoft文档,TimeSpan结构将小时、分钟、秒和毫秒作为整数成员公开。也许你想要:

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

#9


4  

Thanks to Peter for the extension method. I modified it to work with longer time spans better:

感谢彼得的推广方法。我将其修改为更长的工作时间跨度更好:

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

#10


4  

You can use the following code.

您可以使用以下代码。

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

#11


3  

I know this question is older but .Net 4 now has support for Custom TimeSpan formats.

我知道这个问题比较老,但是。net 4现在支持定制的TimeSpan格式。

Also I know it's been mentioned but it caught me out, converting Ticks to DateTime works but doesn't properly handle more than a 24 hour span.

我也知道有人提到过它,但它让我很吃惊,将节拍转换为DateTime有效,但不能正确地处理超过24小时的跨度。

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

That will get you 01:00 not 25:00 as you might expect.

那样你就会得到01:00而不是你可能预期的25:00。

#12


1  

I also had a similar issue and came up with my own extension but it seems to be a bit different than everything else.

我也遇到了类似的问题,并提出了我自己的扩展,但它似乎有点不同于其他的东西。

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

#13


0  

I know this is a late answer but this works for me:

我知道这是一个很晚的回答,但这对我来说很有效:

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

dateDifference should now exclude the parts smaller than a second. Works in .net 2.0 too.

dateDifference现在应该排除小于一秒的部分。也适用于。net 2.0。

#14


-8  

''' <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

#1


36  

Would TimeSpan.ToString() do the trick for you? If not, it looks like the code sample on that page describes how to do custom formatting of a TimeSpan object.

TimeSpan.ToString()能帮你吗?如果不是,则该页面上的代码示例将描述如何执行TimeSpan对象的自定义格式。

#2


158  

I just built a few TimeSpan Extension methods. Thought I could share:

我刚刚构建了一些TimeSpan扩展方法。以为我可以分享:

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

#3


111  

By converting it to a datetime, you can get localized formats:

通过将它转换为datetime,您可以得到本地化的格式:

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

#4


79  

This is the shortest solution.

这是最短的解。

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

#5


30  

Use String.Format() with multiple parameters.

使用String.Format()具有多个参数。

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

#6


8  

The easiest way to format a TimeSpan is to add it to a DateTime and format that:

格式化TimeSpan最简单的方法是将它添加到DateTime中,并将其格式化:

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

This works as long as the time difference is not more than 24 hours.

只要时差不超过24小时就可以。

The Today property returns a DateTime value where the time component is zero, so the time component of the result is the TimeSpan value.

今天的属性返回一个DateTime值,其中时间组件为零,因此结果的时间组件是TimeSpan值。

#7


8  

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

#8


5  

According to the Microsoft documentation, the TimeSpan structure exposes Hours, Minutes, Seconds, and Milliseconds as integer members. Maybe you want something like:

根据Microsoft文档,TimeSpan结构将小时、分钟、秒和毫秒作为整数成员公开。也许你想要:

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

#9


4  

Thanks to Peter for the extension method. I modified it to work with longer time spans better:

感谢彼得的推广方法。我将其修改为更长的工作时间跨度更好:

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

#10


4  

You can use the following code.

您可以使用以下代码。

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

#11


3  

I know this question is older but .Net 4 now has support for Custom TimeSpan formats.

我知道这个问题比较老,但是。net 4现在支持定制的TimeSpan格式。

Also I know it's been mentioned but it caught me out, converting Ticks to DateTime works but doesn't properly handle more than a 24 hour span.

我也知道有人提到过它,但它让我很吃惊,将节拍转换为DateTime有效,但不能正确地处理超过24小时的跨度。

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

That will get you 01:00 not 25:00 as you might expect.

那样你就会得到01:00而不是你可能预期的25:00。

#12


1  

I also had a similar issue and came up with my own extension but it seems to be a bit different than everything else.

我也遇到了类似的问题,并提出了我自己的扩展,但它似乎有点不同于其他的东西。

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

#13


0  

I know this is a late answer but this works for me:

我知道这是一个很晚的回答,但这对我来说很有效:

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

dateDifference should now exclude the parts smaller than a second. Works in .net 2.0 too.

dateDifference现在应该排除小于一秒的部分。也适用于。net 2.0。

#14


-8  

''' <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