141

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

TimeSpan dateDifference = endTime.Subtract(beginTime);

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

If the difference was 00:06:32.4458750

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

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Michael Wheeler
  • 2,459
  • 3
  • 19
  • 26
  • 1
    For a more modern answer go to this question: http://stackoverflow.com/questions/574881/how-can-i-string-format-a-timespan-object-with-a-custom-format-in-net – User Mar 16 '17 at 01:53

14 Answers14

211

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

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;
}
Peter
  • 14,221
  • 15
  • 70
  • 110
  • 2
    What if I don't want to show seconds or days. Not very `extensible` :( but it is certainly the correct direction, you should accept a string like "hh:mm" in here and build the time based on that. Just like `ToString()` I think the answer by @rubenroid is the best answer. – Piotr Kula May 08 '14 at 09:49
  • 2
    @ppumkin His answer displays the result in a totally fixed format. This answer will handle the sensible display of 1 second, right up to hundreds of days. His answer doesn't. – NickG Feb 18 '16 at 15:30
  • 3
    If you only want to display the most important part of `TimeSpan` like "2 days ago" or "15 minutes ago" then check this gist inspired by @Peter anwear: https://gist.github.com/Rychu-Pawel/fefb89e21b764e97e4993ff517ff0129 – Rychu Apr 29 '21 at 08:42
  • @Rychu Your code requires C# 8.0. – Mecanik Dec 22 '22 at 04:53
157

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

new DateTime(timeSpan.Ticks).ToString("HH:mm");
vdboor
  • 21,914
  • 12
  • 83
  • 96
  • 6
    Be sure to use a "HH", not "hh", as a format specifier, otherwise an hours value of 0 might be printed out as "12" - I'm guessing the interpretation of the format specifiers depends on the locale settings. – weiji Mar 31 '10 at 22:04
  • 5
    Also, this has the same issue as Guffa's - if an elapsed time is e.g. 26 hours long, it prints out as "02:00" hours. But I highly prefer this way of printing out formatted strings. – weiji Mar 31 '10 at 22:13
  • I needed a one-liner to use in a VB expression. This was perfect. – Jamie F Apr 04 '12 at 14:44
  • 7
    This method will cause problems if the timespan is negative. – Sugrue Apr 12 '13 at 16:25
  • This doesn't work with "d" days. If you use DateTime then days is always `1`. – Charles Dec 29 '22 at 20:19
139

This is the shortest solution.

timeSpan.ToString(@"hh\:mm");
Ruberoid
  • 1,585
  • 1
  • 9
  • 12
  • 11
    This has a bug. timespan is 1 day, 0 hours and 33 minutes, it will return 00:33 even though it is 24:33 technically. – Rick Rat May 02 '13 at 21:10
  • 13
    @RickRatayczak Imo I wouldn't call it a bug, considering this would, in most cases, be used to display an elapsed time between two timespans. Which rarely exceeds a whole day. Regardless, I see your point, and if that's the case, this solution simply isn't for you. I think it's brilliant though. – Falgantil Feb 04 '14 at 09:43
  • 7
    That's because the format string in the answer doesn't specify the value of the days component of the time span to be shown; 24 hours rolls over into 1 day. Not a bug, its just not showing. – AnotherUser Jun 03 '14 at 15:03
  • 4
    timeSpan.ToString(@"d\:hh\:mm"); – markthewizard1234 May 26 '16 at 10:43
  • If you want an output above 24 hours you can do something like this.. TimeSpan span = TimeSpan.FromMinutes(13425); string hours = string.Format("{0:00}", Math.Round(span.TotalHours, 0)); string minutes = string.Format("{0:00}", span.Minutes); string output = string.Format("{0}:{1}", hours, minutes); – Stuart Oct 13 '16 at 11:05
  • 3
    @BjarkeSøgaard I agree that it's not a bug, if you want to show the day you have to include it in the format string, but where does the assumption come from that the TimeSpan difference between two DateTimes rarely exceeds a whole day? – Thomas Mulder Dec 16 '16 at 14:46
  • From C# Interactive window: new TimeSpan(12, 12, 12).ToString(@"HH\:mm") Input string was not in a correct format. + System.Globalization.TimeSpanFormat.FormatCustomized(System.TimeSpan, string, System.Globalization.DateTimeFormatInfo) + System.Globalization.TimeSpanFormat.Format(System.TimeSpan, string, System.IFormatProvider) + System.TimeSpan.ToString(string) – Venson Nov 16 '17 at 21:02
  • Thanks for your answer. It helps me. – Võ Quang Hòa May 30 '18 at 03:12
  • A slightly different expression: `timeSpan.ToString("hh\\:mm");` – gresolio Dec 02 '20 at 12:02
47

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.

Andy
  • 30,088
  • 6
  • 78
  • 89
  • 1
    I got the same, searched again and updated the link. Does this one work for you? – Andy Aug 16 '09 at 17:51
  • 74
    That page does **not** describe how a programmer can format the TimeSpan string at will. It only describes the format in which the TimeSpan is returned when converted with ToString(). That ToString() does not take any custom arguments like "mm:ss". The code samples only show how the auto-generated string will look like given different TimeSpan values, **not** how to format it at will. You need to convert to DateTime(TimeSpan.Ticks).ToString("mm:ss") first. – MrSparkly Oct 06 '11 at 02:05
  • I converted it in this way => timespan.tostring("%d") + " " +timespan.tostring(@"hh\:mm:\ss"); . The idea is get the required strings separately and join them. – prabhakaran Aug 03 '12 at 08:51
  • 26
    FYI since .Net 4.0, the `ToString` method **can** take a custom format as an argument (like `mm\\:ss`), according to this page : http://msdn.microsoft.com/en-us/library/dd992632.aspx – JYL Nov 02 '13 at 16:03
  • For more options: https://msdn.microsoft.com/en-us/library/ee372287(v=vs.110).aspx – Burak Karakuş Dec 19 '16 at 09:24
  • 1
    The linked article does not include code with any ToString() calls.... – David Jan 31 '17 at 08:32
37

Use String.Format() with multiple parameters.

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);
        }
    }
}
GBegen
  • 6,107
  • 3
  • 31
  • 52
14
   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);
      }
   }
GregC
  • 7,737
  • 2
  • 53
  • 67
8

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

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.

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

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 2
    I think this is the most simple approach. You might want to remove zero hours and minutes like: .ToString("HH 'hrs' mm 'mins' ss 'secs'").Replace("00 hrs", "").Replace("00 mins", "").Trim() – Igor Krupitsky Aug 29 '17 at 18:59
6

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

dateDifference.Hours.ToString() + " hrs, " + dateDifference.Minutes.ToString() + " mins, " + dateDifference.Seconds.ToString() + " secs"
Jason 'Bug' Fenter
  • 1,616
  • 1
  • 16
  • 27
5

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);
  }
}
Edwin
  • 733
  • 8
  • 20
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;
        }
    }
}
DShook
  • 14,833
  • 9
  • 45
  • 55
3

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

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.

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.

Jeff
  • 352
  • 3
  • 11
3

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");
    }
bizah
  • 227
  • 1
  • 2
  • 9
  • 3
    calling this `timeSpan = timeSpan - timeSpan - timeSpan;` as different is an insult to different :-) but I like it, in a perverse sort of way – Marty Neal Feb 28 '13 at 01:48
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.

Kell
  • 3,252
  • 20
  • 19
-13
''' <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
Tom
  • 870
  • 11
  • 13
  • 3
    That's VB. The question asks for C#. – Stephen Kennedy Feb 22 '12 at 22:11
  • @Stephen Kennedy: Really??? [link](http://www.developerfusion.com/tools/convert/vb-to-csharp/) – Tom Jul 24 '12 at 14:44
  • 7
    @user401246 you should've run it through that converter, tested it and put the c# code here instead. As it is, your answer isn't very useful. – Peter Jun 21 '13 at 09:49
  • 1) With all due respect, if *I* were him and someone saved *me* this much coding with the only caveat being that I'd have to copy and paste it into a converter first, *I* would be extremely grateful. If someone from another country gave you the formula to cold fusion, are you just gonna critique him for not giving it to you in your language when a translation is just a couple of clicks away?!? 2) I do not work in C#, so it would not be fitting for me to "test" it in C#. I'm offering what I can easily offer (for free). 3) The O.P. didn't complain. Let him speak for himself. – Tom Nov 07 '13 at 12:52
  • 2
    That is allot of code! ?? What is going on in there? IF a developer wrote this for me I would be forced to cry. – Piotr Kula May 08 '14 at 09:53
  • "allot of code" relative to what?!? In case you didn't notice, it is MUCH, MUCH more flexible (i.e. supporting diff abbrevs, other types of #'s, other languages, etc.) than any of the above solutions. Granted it's way more flexible than what the OP needed but IMHO, not unreasonably so from the perspective of being plopped in a shared lib that could be used in other places in his / other apps. – Tom Jul 19 '14 at 01:13
  • @ppumkin indeed that's a lot of code. – Aloha Nov 15 '16 at 15:34