Reputation: 21
Calculate the number of days, hours, minutes and seconds to another date in swift.
I have already tried using swifts datecomponents to and from function but it is returning the incorrect amount of days for me.
@objc func createCountdown(){
let date = Date()
let calendar = Calendar.current
let components = calendar.dateComponents([.day, .hour, .minute, .second], from: date)
let currentDate = calendar.date(from: components)
let userCalendar = Calendar.current
var birthdayDate = DateComponents()
//Get user's birthday
birthdayDate.month = 4
birthdayDate.day = 16
birthdayDate.hour = 0
birthdayDate.minute = 0
let birthday = userCalendar.date(from: birthdayDate as DateComponents)
let BirthdayDifference = calendar.dateComponents([.day, .hour, .minute, .second], from: currentDate!, to: birthday!)
let daysLeft = BirthdayDifference.day
let hoursLeft = BirthdayDifference.hour
let minutesLeft = BirthdayDifference.minute
let secondsLeft = BirthdayDifference.second
daysLabel.text = String(daysLeft!)
hoursLabel.text = String(hoursLeft!)
minutesLabel.text = String(minutesLeft!)
secondsLabel.text = String(secondsLeft!)
}
The test date in the code is the birthday values. I'm simply trying to make a day, hour, minute, and second countdown to the specified birthday from the current date.
The output for this is 74 days, but obviously it is more than 74 days from today, 12/31/2018 to april 16th, 4/16/2019. That is around 105 days, not 74. Any advice is greatly appreciated.
Thank you.
Upvotes: 2
Views: 2806
Reputation: 236315
You need to find out when is the next birth date based on the day and month of birthday. You can use Calendar's method nextDate(after: Date, matching: DateComponents)
func nextDate(after date: Date, matching components: DateComponents, matchingPolicy: Calendar.MatchingPolicy, repeatedTimePolicy: Calendar.RepeatedTimePolicy = default, direction: Calendar.SearchDirection = default) -> Date?
let birthDateCoponents = DateComponents(month: 4, day: 16)
let nextBirthDate = Calendar.current.nextDate(after: Date(), matching: birthDateCoponents, matchingPolicy: .nextTime)!
let difference = Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date(), to: nextBirthDate)
difference.day // 105
difference.hour // 2
difference.minute // 5
difference.second // 30
When displaying it to the user you can use DateComponentsFormatter with the appropriate unitsStyle
. You can see below how it would look like when using .full
style and limiting the units to .day, .hour, .minute, .second
:
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.day, .hour, .minute, .second]
formatter.unitsStyle = .full
formatter.string(from: Date(), to: nextBirthDate) // "105 days, 1 hour, 44 minutes, 36 seconds"
Upvotes: 4