Tuesday, November 22, 2005

Convert Seconds to Countdown Time

I seem to find myself doing alot of “countdown” type app’s/features. For example, right now I’m working on a “ping this list of machines every ## minutes” control.

When I build these kinds of things, I like giving the user an idea when the next event will happen. Hence a countdown…

I have a timer set to a 1 second interval (Timer.Interval = 1000) and each tick I decrement the remaining seconds by one. When the remaining seconds hits zero I reset the remaining seconds to the master interval and fire off the “event” (which with VB/VS 2005, I’m using the BackgroundWorker component).

While the time is counting down, I like to give the user a Minutes:Seconds countdown. I find myself reinventing this wheel over and over. I’m creating a snippet now, but also wanted to post the code here…

This function will take in the seconds and return a “m:ss” string. For example, 119 will return “1:59”, 61 will return “1:01”, 59 will return “59”

It’s quick and dirty, but gets the job done.

Private Function ConvertSecondstoCountdownTime(ByVal Seconds As Integer) _
                    As String

    Dim Result As String
    Dim Minutes As Integer
    Dim RemainingSeconds As Integer

    If Seconds < 60 Then
      Result = Seconds.ToString

    Else

      Minutes = Seconds \ 60

      RemainingSeconds = Seconds - (Minutes * 60)

      If RemainingSeconds < 10 Then
        Result = String.Format("{0:G}:0{1:G}", Minutes, _
                                RemainingSeconds)
      Else
        Result = String.Format("{0:G}:{1:G}", Minutes, _
                                RemainingSeconds)

      End If

    End If

    Return Result

  End Function

3 comments:

JP said...

In your stated use case it very likely doesn't matter, but delays in the ui code "getting around" to firing the event, plus the level of precision in the timer itself, can lead to innaccuracies. One approach I have taken is to record the wall clock time when the countdown starts, and subtract it from the current time to get the difference. The minus operator for 2 DateTimes results in a TimeSpan result, which is even pretty handy for displaying what you are getting at.

JP said...

Quick and dirty example - I am not a VB Coder

Public Class Countdown
Dim start As DateTime
Dim length As TimeSpan

Public Sub StartTimer(countdownLength as TimeSpan)
start = DateTime.Now
length = countdownLength
End Sub

Public Function GetRemaining() As TimeSpan
Dim remaining As TimeSpan
remaining = (length - (DateTime.Now - start))
If (remaining.TotalSeconds < 1) Then
remaining = TimeSpan.FromSeconds(0)
End If
Return remaining
End Function

Public Overrides Function ToString() As String
Dim remaining As TimeSpan
remaining = GetRemaining()
Return String.Format("{0:G}:{1:G}", remaining.Minutes, remaining.Seconds)
End Function

End Class

Greg said...

You are very right... The Timer is "sloppy", but in my case it does okay.

If truly accurate timing/intervals/etc are needed the Timer just isn't the right tool.

Thanks for the code sample. Something for me to think about.

I like the thought of using of DateTime and TimeSpan types...

Thank you...