Swift 3 - 比较日期对象

116
我正在将我的应用程序更新到Swift 3.0语法(我知道它仍处于测试版,但我想尽早准备好)。在之前的Xcode Beta(Beta 5)中,我能够使用操作数<,>和==比较两个对象。但在最新的测试版(Beta 6)中,这不再起作用了。以下是一些屏幕截图:

enter image description here enter image description here

如您在两个截图中所见,这是两个Date对象。但我收到以下错误: enter image description here 我做错了什么?这些函数仍然在Date类中声明:

static func >(Date, Date)

如果左侧的日期比右侧的日期晚,则返回true。

这只是Beta版的错误还是我做错了什么?

2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { } 在我的 Xcode 8 beta 6 中可以运行。 - Martin R
1
是的。- 您应该在报告导航器中查找完整的错误消息。 - Martin R
谢谢@MartinR!我不知道我可以“深入”错误并获得更多信息。帮了我很多! - beeef
接受正确答案 - Ankit Thakur
14个回答

189

我已经尝试过这段代码(在Xcode 8 Beta 6中),它可以正常工作。

let date1 = Date()
let date2 = Date().addingTimeInterval(100)

if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }

如果我想忽略时间。例如 2019-05-14 12:08:14 +0000 == 2019-05-14 应该返回 true。那么怎么办? - Awais Fayyaz
如果您想比较日期而不考虑DateComponent,则需要从日期中获取所需的组件。然后从DateComponents获取日期并进行比较。 - Giorgio Doganiero

59

Date 在 Swift 3 中遵循 ComparableEquatable 协议

本答案是对 @Ankit Thakur 答案的补充。

从 Swift 3 开始,Date 结构体(基于底层的 NSDate 类)采用了 ComparableEquatable 协议。

  • Comparable 要求 Date 实现运算符:<<=>>=
  • Equatable 要求 Date 实现 == 运算符。
  • Equatable 允许 Date 使用默认实现的 != 运算符(它是 Equatable== 运算符实现的反面)。

以下示例代码演示了如何使用这些比较运算符,并使用 print 语句确认哪些比较是真的。

比较函数

import Foundation

func describeComparison(date1: Date, date2: Date) -> String {

    var descriptionArray: [String] = []

    if date1 < date2 {
        descriptionArray.append("date1 < date2")
    }

    if date1 <= date2 {
        descriptionArray.append("date1 <= date2")
    }

    if date1 > date2 {
        descriptionArray.append("date1 > date2")
    }

    if date1 >= date2 {
        descriptionArray.append("date1 >= date2")
    }

    if date1 == date2 {
        descriptionArray.append("date1 == date2")
    }

    if date1 != date2 {
        descriptionArray.append("date1 != date2")
    }

    return descriptionArray.joined(separator: ",  ")
}

使用示例

let now = Date()

describeComparison(date1: now, date2: now.addingTimeInterval(1))
// date1 < date2,  date1 <= date2,  date1 != date2

describeComparison(date1: now, date2: now.addingTimeInterval(-1))
// date1 > date2,  date1 >= date2,  date1 != date2

describeComparison(date1: now, date2: now)
// date1 <= date2,  date1 >= date2,  date1 == date2

34

从Swift 3及以上版本开始,日期(Date)已经实现了Comparable协议,因此我们可以直接比较日期,如下:

let date1 = Date()
let date2 = Date().addingTimeInterval(50)

let isGreater = date1 > date2
print(isGreater)

let isSmaller = date1 < date2
print(isSmaller)

let isEqual = date1 == date2
print(isEqual)

或者,我们可以在 Date 上创建扩展。

extension Date {

  func isEqualTo(_ date: Date) -> Bool {
    return self == date
  }
  
  func isGreaterThan(_ date: Date) -> Bool {
     return self > date
  }
  
  func isSmallerThan(_ date: Date) -> Bool {
     return self < date
  }
}

应用: let isEqual = date1.isEqualTo(date2)


1
如果我想忽略时间。例如 2019-05-14 12:08:14 +0000 == 2019-05-14 应该返回 true。那么接下来呢? - Awais Fayyaz

25

不要使用比较运算符<, >, ==, !=
请使用compare(_ other: Date)函数。

用法

// Get current date
let dateA = Date()

// Get a later date (after a couple of milliseconds)
let dateB = Date()

// Compare them using switch
switch dateA.compare(dateB) {
    case .orderedAscending     :   print("Date A is earlier than date B")
    case .orderedDescending    :   print("Date A is later than date B")
    case .orderedSame          :   print("The two dates are the same")
}

// Compare them using if
if dateA.compare(dateB) == .orderedAscending {
    datePickerTo.date = datePicker.date
}

3
为什么不要使用比较运算符 <、>、==、!=? - Kai Huppmann

11

如果你想忽略秒,例如:

func isDate(Date, equalTo: Date, toUnitGranularity: NSCalendar.Unit) -> Bool

比如,比较它是否为同一天:

Calendar.current.isDate(date1, equalTo: date2, toGranularity: .day)

你的回答很有效,谢谢 :) - steveSarsawa
非常感谢!这正是我正在寻找的东西。 - marticztn

9

对我来说,问题在于我有自己的Date类扩展,定义了所有比较运算符。现在(从Swift 3开始),由于Date是可比较的,这些扩展已不再需要。因此,我将它们注释掉,然后它就可以工作了。


8

SWIFT 3: 我不知道这是否是您要找的内容。但是我将一个字符串与当前时间戳进行比较,以查看我的字符串是否早于现在。

func checkTimeStamp(date: String!) -> Bool {
        let dateFormatter: DateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        dateFormatter.locale = Locale(identifier:"en_US_POSIX")
        let datecomponents = dateFormatter.date(from: date)

        let now = Date()

        if (datecomponents! >= now) {
            return true
        } else {
            return false
        }
    }

使用它的方法如下:
if (checkTimeStamp(date:"2016-11-21 12:00:00") == false) {
    // Do something
}

6

如果我只想比较年月日而不包括时间,可以按照以下方式操作:

     let order = Calendar.current.compare(self.startDate, to: compareDate!, toGranularity: .day)  

                      switch order {
                        case .orderedAscending:
                            print("\(gpsDate) is after \(self.startDate)")
                        case .orderedDescending:
                            print("\(gpsDate) is before \(self.startDate)")
                        default:
                            print("\(gpsDate) is the same as \(self.startDate)")
                        }

1
extension Date {
 func isBetween(_ date1: Date, and date2: Date) -> Bool {
    return (min(date1, date2) ... max(date1, date2)).contains(self)
  }
}

let resultArray = dateArray.filter { $0.dateObj!.isBetween(startDate, and: endDate) }

1
另一种方式是:
    switch date1.compare(date2) {
        case .orderedAscending:
            break

        case .orderedDescending:
            break;

        case .orderedSame:
            break
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接