41

I have an NSTimer which counts DOWN from 2 hours until 0.

Here are some of my code:

var timer = NSTimer()
let timeInterval:NSTimeInterval = 0.5
let timerEnd:NSTimeInterval = 0.0
var timeCount:NSTimeInterval = 7200.0 // seconds or 2 hours

// TimeString Function

func timeString(time:NSTimeInterval) -> String {
    let minutes = Int(time) / 60
    let seconds = time - Double(minutes) * 60
    let secondsFraction = seconds - Double(Int(seconds))
    return String(format:"%02i:%02i.%01i",minutes,Int(seconds),Int(secondsFraction * 10.0))
}

The Timer Label is:

TimerLabel.text = "Time: \(timeString(timeCount))"

HOWEVER, my timer label shows as:

Time: 200:59.0

How do I format my timer label to look like this:

Time: 01:59:59 // (which is hours:minutes:seconds)?

[Please note that I have no problems with my countdown timer, I only need to know how to CHANGE THE TIME FORMAT using the TimeString function.]

EDIT: Someone mentioned that my question is a possible duplicate of this one: Swift - iOS - Dates and times in different format. HOWEVER, I am asking on how do I change the time format using the TimeString function that I gave above. I am not asking for another WAY on how to do it.

For instance:

let minutes = Int(time) / 60

gives me "200" minutes. etc.

Community
  • 1
  • 1
Juma Orido
  • 481
  • 1
  • 4
  • 11
  • 2
    Possible duplicate of [Swift - IOS - Dates and times in different format](http://stackoverflow.com/questions/28489227/swift-ios-dates-and-times-in-different-format) – Abhijeet Feb 05 '16 at 03:25
  • Where's your calculation of hours? – rmaddy Feb 05 '16 at 03:29
  • 3
    @Abhijeet That is not even remotely close to being a duplicate of this question. This question is not dealing with an `NSDate` and this question's solution has nothing to do with `NSDateFormatter`. – rmaddy Feb 05 '16 at 03:39

5 Answers5

112

Your calculations are all wrong.

let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
rmaddy
  • 314,917
  • 42
  • 532
  • 579
92

@rmaddy's solution is accurate and answers the question. However, neither the question nor the solution take into account international users. I suggest using DateComponentsFormatter and let the framework handle the calculations and formatting. Doing so makes your code less error prone and more future proof.

I came across this blog post that provides a concise solution: http://crunchybagel.com/formatting-a-duration-with-nsdatecomponentsformatter/

Pulled from that post, this is the code snippet that would replace the code you're currently using to make your calculations. Updated for Swift 3:

let duration: TimeInterval = 7200.0

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional // Use the appropriate positioning for the current locale
formatter.allowedUnits = [ .hour, .minute, .second ] // Units to display in the formatted string
formatter.zeroFormattingBehavior = [ .pad ] // Pad with zeroes where appropriate for the locale

let formattedDuration = formatter.string(from: duration) 
Mark Suman
  • 10,430
  • 2
  • 27
  • 23
  • Good point, however there are certain cases where maddy's answer is just enough. For example if you make application just for one localisation. – Markus Jul 19 '17 at 08:31
  • 2
    Great answer, I had forgotten how to do this. – Forest Kunecke Aug 12 '17 at 19:38
  • 2
    Great answer. Thanks – crashoverride777 Mar 15 '18 at 10:15
  • 1
    @NathanHosselton No since the OP specifically stated: *"I am asking on how do I change the time format using the TimeString function that I gave above. I am not asking for another WAY on how to do it."*. Using `DateComponentsFormatter` is what most people should use but it's not what the OP wanted. – rmaddy Jan 08 '19 at 03:40
  • 1
    For people coming from Google: The answer above no longer works. Not sure if the API changed or if it was wrong to begin with, but to fix it don't pass duration to formatter. You need to pass `DateComponents`. See this post for more clarity: https://nshipster.com/formatter/#datecomponentsformatter – derickito Jan 26 '21 at 02:53
7

Swift5

var totalSecond = Int()
var timer:Timer?

call startTimer() based on requirement-

func startTimer(){
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)
}

@objc func countdown() {
    var hours: Int
    var minutes: Int
    var seconds: Int

    if totalSecond == 0 {
        timer?.invalidate()
    }
    totalSecond = totalSecond - 1
    hours = totalSecond / 3600
    minutes = (totalSecond % 3600) / 60
    seconds = (totalSecond % 3600) % 60
    timeLabel.text = String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}

Done

Rohit Nishad
  • 428
  • 4
  • 7
1

The best way to implement a Timer in Swift (swift 4 works fine). Declare the variable secs: Int and assign the value, in seconds, of the timer. Then with the Timer () function, discount one second at a time and pass it to this function.

var secs = 0
var timer = Timer()

func startTimer(segs: Int) {
        seg = segs
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerDiscount), userInfo: nil, repeats: true)
    }

func timerDiscount() {
            let hours = secs / 3600
            let mins = secs / 60 % 60
            let secs = secs % 60
            let restTime = ((hours<10) ? "0" : "") + String(hours) + ":" + ((mins<10) ? "0" : "") + String(mins) + ":" + ((secs<10) ? "0" : "") + String(secs)
}
mjoe7
  • 134
  • 6
oscar castellon
  • 3,048
  • 30
  • 19
0

Declare the variables hours ,minutes and seconds and copy paste the below code it works fine.

      if counter > 0 {

        let hours = counter / 3600

        let minutes = counter / 60

        let seconds = counter % 60

        counter = counter - 1

        timerLbl.text = "\(hours):\(minutes):\(seconds)"

    }
Prashanth Thota
  • 157
  • 1
  • 11
  • While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find [how to write a good answer](https://stackoverflow.com/help/how-to-answer) very helpful. Please edit your answer. – hellow Nov 14 '18 at 07:17