在 Swift 中计算两个日期之间的差异
Posted
技术标签:
【中文标题】在 Swift 中计算两个日期之间的差异【英文标题】:Calculating the difference between two dates in Swift 【发布时间】:2018-11-29 16:44:37 【问题描述】:我已经看到了许多方法如何根据特定日期组件计算两个日期之间的差异,例如以天、小时、月等为单位(参见this answer on ***):
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
我还没有看到如何使用实际的Date
对象进行计算。类似的东西
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
我已经看到了 DateInterval
类型,它是在 ios 10 中引入的,但根据文档
[it] 不支持反向间隔,即持续时间小于 0 且结束日期早于开始日期的时间间隔。
这使得用日期计算本来就很困难——尤其是当您不知道哪个是较早的日期时。
是否有任何简洁的方法可以直接计算Date
s 之间的时间差(并将它们再次添加到Date
实例中)不用他们的timeIntervalSinceReferenceDate
计算?
【问题讨论】:
Apple Documentation 描述了一个比较函数,它将为您排序日期,以便您进行评估。timeIntervalSinceReferenceDate
有什么问题?
@Jake:当然我可以比较日期,但我无法计算两个日期之间的时间间隔,然后我可以将其添加到另一个日期。我在我的问题中包含的功能只是我编造的一个示例,以展示它的一些应用,诚然,这是一个非常简单的功能,可以以更好的方式实现。但这不是问题。问题是如何使用直观的语法轻松计算日期差异。
@AndréSlotta:问题在于它使代码的可读性、美观性和直观性降低:toDate - fromDate
比 toDate.timeIntervalSinceReferenceDate - fromDate.timeIntervalSinceReferenceDate
更易于阅读。
另外,我不清楚为什么 Swift 不允许我直接减去两个日期。
【参考方案1】:
我最终为Date
创建了一个自定义运算符:
extension Date
static func - (lhs: Date, rhs: Date) -> TimeInterval
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
使用此运算符,我现在可以在更抽象的层面上计算两个日期之间的差异,而无需关心 timeIntervalSinceReferenceDate
或参考日期究竟是什么——并且不会丢失精度,例如:
let delta = toDate - fromDate
显然,我并没有改变太多,但对我来说,它更具可读性和结果:Swift 已经为 Date
和 TimeInterval
实现了 +
运算符:
/// Returns a `Date` with a specified amount of time added to it. public static func + (lhs: Date, rhs: TimeInterval) -> Date
所以已经支持了
Date + TimeInterval = Date
因此,它也应该支持
Date - Date = TimeInterval
在我看来,这就是我在 -
运算符的简单实现中添加的内容。现在我可以完全按照我的问题中提到的那样编写示例函数:
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`
这很可能有一些我目前不知道的缺点,我很想听听您对此的看法。
【讨论】:
【参考方案2】:您可以使用自定义运算符进行扩展,并返回元组
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)
使用:
let interval = Date() - updatedDate
print(interval.day)
print(interval.month)
print(interval.hour)
【讨论】:
这对我帮助很大。 在 swift 5 中正常工作。谢谢兄弟【参考方案3】:只需toDate.timeIntervalSince(fromDate)
。
在不添加任何扩展的情况下重新实现您的功能:
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)
【讨论】:
【参考方案4】:我找到了一个内置的解决方案来计算两个日期之间的差异。
let delta = toDate.timeIntervalSince(fromDate)
【讨论】:
This has been suggested @cakraww 已经。【参考方案5】:你可以使用:
let delta = fromDate.distance(to: toDate)
【讨论】:
【参考方案6】:比如……
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())!
【讨论】:
那是再次使用组件,而不是固有日期。delta
将是一个表示秒数的整数,因此对于任何不是整秒的倍数的日期,此函数都会丢失精度。以上是关于在 Swift 中计算两个日期之间的差异的主要内容,如果未能解决你的问题,请参考以下文章