Convert integer to full text string duration I have a function I have written in VB for use in SSRS 2012. It takes an integer and converts it to full text duration - for example 900 becomes "15 minutes", 9000 becomes "2 hours 30 minutes", and 7201 is "2 hours 1 second".

The code works, and is:

Public Function SecondsFullText(ByVal TotalSeconds As Integer) As String

    Dim hours As Integer = new Integer()
    Dim minutes As Integer = new Integer()
    Dim seconds As Integer = new Integer()

    Dim hourString as String = ""
    Dim minuteString as String = ""
    Dim secondString as String = ""

    hours = floor(TotalSeconds / 3600)
    minutes = floor((TotalSeconds mod 3600) / 60)
    seconds = (TotalSeconds mod 3600) mod 60

    If hours = 1 Then
        hourString = Cstr(hours) &amp; " hour"
    Else If hours &gt; 1 Then
        hourString = Cstr(hours) &amp; " hours"
    End If

    If minutes = 1 Then
        minuteString = Cstr(minutes) &amp; " minute"
    Else If minutes &gt; 1 Then
        minuteString = Cstr(minutes) &amp; " minutes"
    End If

    If seconds = 1 Then
        secondString = Cstr(seconds) &amp; " second"
    Else If seconds &gt; 1 Then
        secondString = Cstr(seconds) &amp; " seconds"
    End If

    If hours &gt; 0 and (minutes &gt; 0 or seconds &gt; 0) Then
        hourString = hourString &amp; " "
    End If

    If minutes &gt; 0 and seconds &gt; 0 Then
        minuteString = minuteString &amp; " "
    End If

    return hourString &amp; minuteString &amp; secondString
End Function


My question is: how do I make this better? It seems very clunky, with too many IFs to handle the different possibilities for single/plural, spaces, etc.  I feel that this can be better, but I'm not sure how.

This is called in Report Builder 3.0 / SSRS 2012 with this expression: =Code.SecondsFullText(Parameters!Integer.Value)
You should look into the TimeSpan struct, which provides a nice method TimeSpan.FromSeconds().

Having filled a TimeSpan struct by e.g calling the FromSeconds() method, you can just access its properties Seconds, Minutes and Hours.

Instead of concating strings like you do, you should consider to use a StringBuilder.  

To get rid of the If ... Else If you can just use the singular and only if the value is greater than 1 you add a s to the string/StringBuilder.  

Based on the .NET Naming Guidelines method parameters should be named using camelCase casing hence TotalSeconds should be totalSeconds

Implementing the mentioned points will look like so  

Public Function SecondsFullText(ByVal totalSeconds As Double) As String

    Dim timeSpan As TimeSpan = TimeSpan.FromSeconds(totalSeconds)
    Dim stringBuilder As StringBuilder = New StringBuilder()

    Dim hours As Integer = timeSpan.Hours
    Dim minutes As Integer = timeSpan.Minutes
    Dim seconds As Integer = timeSpan.Seconds

    stringBuilder.Append(ToText(hours, "hour"))
    If hours &gt; 0 AndAlso (minutes &gt; 0 OrElse seconds &gt; 0) Then
        stringBuilder.Append(" ")
    End If
    stringBuilder.Append(ToText(minutes, "minute"))
    If minutes &gt; 0 AndAlso seconds &gt; 0 Then
        stringBuilder.Append(" ")
    End If
    stringBuilder.Append(ToText(seconds, "second"))
    Return stringBuilder.ToString()

End Function

Private Function ToText(value As Integer, singularName As String) As String

    If value = 0 Then Return String.Empty
    If value = 1 Then Return String.Format("{0} {1}", value, singularName)
    Return String.Format("{0} {1}s", value, singularName)

End Function