Calculating the difference between two dates in Swift
Solution 1
I ended up creating a custom operator for Date
:
extension Date {
static func - (lhs: Date, rhs: Date) -> TimeInterval {
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
}
}
With this operator I can now compute the difference between two dates on a more abstract level without caring about timeIntervalSinceReferenceDate
or what exactly the reference date is – and without losing precision, for example:
let delta = toDate - fromDate
Obviously, I didn't change much, but for me it's a lot more readable and consequent: Swift has the +
operator already implemented for a Date
and a TimeInterval
:
/// Returns a `Date` with a specified amount of time added to it. public static func + (lhs: Date, rhs: TimeInterval) -> Date
So it's already supporting
Date + TimeInterval = Date
Consequently, it should also support
Date - Date = TimeInterval
in my opinion and that's what I added with the simple implementation of the -
operator. Now I can simply write the example function exactly as mentioned in my question:
func computeNewDate(from fromDate: Date, to toDate: Date) -> Date
let delta = toDate - fromDate // `Date` - `Date` = `TimeInterval`
let today = Date()
if delta < 0 {
return today
} else {
return today + delta // `Date` + `TimeInterval` = `Date`
}
}
It might very well be that this has some downsides that I'm not aware of at this moment and I'd love to hear your thoughts on this.
Solution 2
You can extension with custom operator, and return tuples
extension Date {
static func -(recent: Date, previous: Date) -> (month: Int?, day: Int?, hour: Int?, minute: Int?, second: Int?) {
let day = Calendar.current.dateComponents([.day], from: previous, to: recent).day
let month = Calendar.current.dateComponents([.month], from: previous, to: recent).month
let hour = Calendar.current.dateComponents([.hour], from: previous, to: recent).hour
let minute = Calendar.current.dateComponents([.minute], from: previous, to: recent).minute
let second = Calendar.current.dateComponents([.second], from: previous, to: recent).second
return (month: month, day: day, hour: hour, minute: minute, second: second)
}
}
Using:
let interval = Date() - updatedDate
print(interval.day)
print(interval.month)
print(interval.hour)
Solution 3
Simply toDate.timeIntervalSince(fromDate)
.
To reimplement your function without adding any extension:
func computeNewDate(from fromDate: Date, to toDate: Date) -> Date {
let delta = toDate.timeIntervalSince(fromDate)
let today = Date()
if delta < 0 {
return today
} else {
return today.addingTimeInterval(delta)
}
}
Solution 4
I found a builtin solution to calculate the difference between 2 dates.
let delta = toDate.timeIntervalSince(fromDate)
Solution 5
You can use :
let delta = fromDate.distance(to: toDate)
![Mischa](https://i.stack.imgur.com/Z4s2Q.jpg?s=256&g=1)
Mischa
Watch my talks on ▶️ The Art of Designing Code ▶️ Auto Layout
Updated on February 14, 2021Comments
-
Mischa over 3 years
I've seen many approaches how to compute the difference between two dates in terms of a particular date component, e.g. in days, hours, months etc. (see this answer on Stackoverflow):
Calendar.current.dateComponents([.hour], from: fromDate, to: toDate).hour Calendar.current.dateComponents([.day], from: fromDate, to: toDate).day Calendar.current.dateComponents([.month], from: fromDate, to: toDate).month
What I haven't seen is how to make calculations with the actual
Date
objects. Something likefunc computeNewDate(from fromDate: Date, to toDate: Date) -> Date let delta = toDate - fromDate let today = Date() if delta < 0 { return today } else { return today + delta } }
I have seen the
DateInterval
type which as introduced in iOS 10 but according to the documentation[it] does not support reverse intervals i.e. intervals where the duration is less than 0 and the end date occurs earlier in time than the start date.
That makes it inherently difficult to calculate with dates – especially when you don't know which one is the earlier date.
Is there any clean and neat approach to compute time differences between
Date
s directly (and adding them toDate
instances again) without computing with theirtimeIntervalSinceReferenceDate
?