在 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 且结束日期早于开始日期的时间间隔。

这使得用日期计算本来就很困难——尤其是当您不知道哪个是较早的日期时。

是否有任何简洁的方法可以直接计算Dates 之间的时间差(并将它们再次添加到Date 实例中)不用他们的timeIntervalSinceReferenceDate 计算?

【问题讨论】:

Apple Documentation 描述了一个比较函数,它将为您排序日期,以便您进行评估。 timeIntervalSinceReferenceDate 有什么问题? @Jake:当然我可以比较日期,但我无法计算两个日期之间的时间间隔,然后我可以将其添加到另一个日期。我在我的问题中包含的功能只是我编造的一个示例,以展示它的一些应用,诚然,这是一个非常简单的功能,可以以更好的方式实现。但这不是问题。问题是如何使用直观的语法轻松计算日期差异。 @AndréSlotta:问题在于它使代码的可读性、美观性和直观性降低:toDate - fromDatetoDate.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 已经为 DateTimeInterval 实现了 + 运算符:

/// 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 中计算两个日期之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

如何计算两个日期之间的差异?

如何在java中计算两个日期之间的年龄或差异

在 C 中计算两个 ISO 8601 日期(包括毫秒)之间的差异

如何使用 PHP 计算两个日期之间的差异?

计算两个日期时间odoo 10之间的差异[重复]

如何计算两个日期之间的差异