I've seen many approaches how to compute the difference between two dates in terms of a particular date component, eg 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 like
func 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 ie 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 to Date
instances again) without computing with their timeIntervalSinceReferenceDate
?
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.
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)
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)
}
}
我找到了一个内置解决方案来计算两个日期之间的差异。
let delta = toDate.timeIntervalSince(fromDate)
您可以使用 :
let delta = fromDate.distance(to: toDate)
How about something like…
func computeNewDate(from fromDate: Date, to toDate: Date) -> Date {
let delta = Calendar.current.dateComponents([.second], from: fromDate, to: toDate).second!
return Calendar.current.date(byAdding: .second, value: delta, to: Date())!
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.