Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift countdown timer labels for Days/Hours/Minutes/Seconds

I'm creating a countdown timer that counts down to an NSDate set in a UIDatePicker. I have a label that shows the date we're counting down to and that works fine.

What I'm also trying to add is labels for the number of whole days left and number of hours/minutes/seconds left in the current day (i.e. never more than 23/59/59) Here's what I've done at the minute but it obviously shows the values for the whole countdown. Hoping someone can help me work out the correct logic here.

let secondsLeft = sender.date.timeIntervalSinceDate(NSDate())
hoursLabel.text = String(secondsLeft % 3600)
minutesLabel.text = String((secondsLeft / 60) % 60)
secondsLabel.text = String(secondsLeft % 60)

I guess what I'm looking for is some swift equivalent of the datetime class you get in php

like image 545
Chris Byatt Avatar asked Oct 13 '15 22:10

Chris Byatt


3 Answers

Got it - for Swift 2

let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: NSDate(), toDate: sender.date, options: [])
daysLabel.text = String(components.day)
hoursLabel.text = String(components.hour)
minutesLabel.text = String(components.minute)
secondsLabel.text = String(components.second)
like image 77
Chris Byatt Avatar answered Nov 15 '22 11:11

Chris Byatt


Take a look at the NSCalendar class. Specifically look at the method components:fromDate:toDate:options: That lets you take 2 dates and calculate the difference between them using whatever units you specify.

It's also localizable, so if you use the current calendar and the user uses the Chinese, Hebrew, or Arabic calendar then the calculations will give you results correct for that calendar.

like image 2
Duncan C Avatar answered Nov 15 '22 11:11

Duncan C


Here's a Swift 4 version of Chris Byatt's answer that is also playground-friendly:

import UIKit

let calendar = Calendar.current
let now = Date()
let futureDate = Date.distantFuture

let components = calendar.dateComponents([.day, .hour, .minute, .second], from: now, to: futureDate)

let daysLabel = UILabel()
let hoursLabel = UILabel()
let minutesLabel = UILabel()
let secondsLabel = UILabel()

daysLabel.text = String(describing: components.day)
hoursLabel.text = String(describing: components.hour)
minutesLabel.text = String(describing: components.minute)
secondsLabel.text = String(describing: components.second)

print(components) // day: 723942 hour: 23 minute: 56 second: 0 isLeapMonth: false

// Bonus: here's an easy way to print grammatically correct labels based on numbers
if let seconds = components.second {
    let labelText = "\(seconds) \(seconds == 1 ? "second" : "seconds")"
    print(labelText) // 0 seconds, 1 second, 2 seconds, etc.
}
like image 1
Scott Gardner Avatar answered Nov 15 '22 11:11

Scott Gardner