Search code examples
swiftxcodenstimerdate-format

NSTimer countdown producing 0 twice


I have some code that gets the difference of time between today and another time string.

The display is refreshed every second by using NSTimer.scheduledTimerWithTimeInterval.

Everything is working fine except when the timer reaches 0. 0 is displayed twice.

Example:

3,2,1,0,0,-1,-2 

enter image description here

Below is my code done done in playground:

   //: Playground - Time Countdown
import UIKit
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely()

class MyClass {

    var totalSecondsText = ""

    init(classSecondsText: String){
        totalSecondsText = classSecondsText
    }

    @objc func ontimer(timer:NSTimer!){

        let total = determineTimeDifference(totalSecondsText)

                let (hour,min,sec) = secondsConverter(total)

                if hour >= 1 {
                    if min >= 1 {
                        NSLog(String(hour)+"h "+String(min)+"m")
                    }else {
                        NSLog(String(hour)+"h")
                    }
                }else{
                    if min >= 1{
                        NSLog(String(min)+"m "+String(sec)+"s")
                    } else if min > -1 {
                        NSLog(String(sec)+"s")
                    } else if min <= -1 {
                        NSLog(String(min)+"m")
                    }
                }
    }

    func determineTimeDifference(timeInputed: String) -> Int {

         let dateFormat = NSDateFormatter()
         dateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
         let finalDate = dateFormat.dateFromString(raceTime)
         let differenceTimeInSeconds =  (finalDate?.timeIntervalSinceNow)!

    return differenceInSeconds

   }

    func secondsConverter (seconds : Int) -> (Int  , Int, Int){
        return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
    }

}

// Add +1 minute on time to test.
var dateString = "2016-08-31T6:49:00Z"

NSTimer.scheduledTimerWithTimeInterval(1, target: MyClass(classSecondsText: dateString), selector: #selector(MyClass.ontimer(_:)), userInfo: nil, repeats: true)

Any idea on what went wrong?

Update:

As promised, here is the bug fix for this issue:

    func determineTimeDifference(timeInputed: String) -> Int {

             let dateFormat = NSDateFormatter()
             dateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
             let finalDate = dateFormat.dateFromString(raceTime)?.timeIntervalSince1970
             let dateNow = NSDate().timeIntervalSince1970
             let differenceTimeInSeconds = Int(finalDate) -  Int(dateNow)

     return differenceInSeconds
}

Solution

  • Your code is well provided, and conditions are placed correctly. It looks like Data.components is not handling counting difference correctly. It can be caused by rounding of seconds component.

    If counting before the moment, when current time and final time are equal, (reach 0,0), result comes with an error of -1.

    When I updated your code with additional prints, this was shown:

    CURRENT date: 2016-08-31 13:10:57 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: 2s (BAD)
    CURRENT unix: 1472649057.28685 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  -3.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    2s 
    
    CURRENT date: 2016-08-31 13:10:58 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: 1s (BAD)
    CURRENT unix: 1472649058.28734 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  -2.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    1s 
    
    CURRENT date: 2016-08-31 13:10:59 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: 0s (BAD)
    CURRENT unix: 1472649059.28731 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  -1.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    0s 
    
    CURRENT date: 2016-08-31 13:11:00 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: 0s (OK)
    CURRENT unix: 1472649060.28731 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  0.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    0s 
    
    CURRENT date: 2016-08-31 13:11:01 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: -1s (OK)
    CURRENT unix: 1472649061.28731 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  1.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    -1s 
    
    CURRENT date: 2016-08-31 13:11:02 +0000 - FINAL date: 2016-08-31 13:11:00 +0000
    -->> diff by DateComponents: -2s (OK)
    CURRENT unix: 1472649062.28729 - FINAL unix: 1472649060.0
    --->>> Diff in UNIX:  2.0s (counted as Rounded CURRENT UNIX - FINAL UNIX)
    -2s 
    

    So if used counting by difference between rounded unix times, the results are correct.

    Conclusion: The error sometimes comes before equation, sometimes comes after that. It depends on what time was that script launched. If counting by data components starts with an error, it cleans after 0, 0. If counting starts with correct result, then results start to bring error results. That's why zero appears twice - at the moment when result changes its precise status.