Swift 3-比较 Date 对象

我正在更新我的应用程序到 Swift 3.0语法(我知道它仍处于测试阶段,但我希望它一发布就能做好准备)。

在 Xcode 的 Beta (Beta 5)之前,我能够使用操作数 <>==比较两个 Date对象。但是在最新的测试版(Beta 6)中,这种方法已经失效了。下面是一些截图:

enter image description here enter image description here

正如你在两个截图中看到的,这是两个 Date对象,但是我得到了以下错误: enter image description here

我做错了什么? 函数仍然在 Date类中声明:

static func >(Date, Date)

如果左边的 Date 在时间上晚于右边的 Date,则返回 true。

这只是个测试版错误,还是我做错了什么?

170378 次浏览

I have tried this snippet (in Xcode 8 Beta 6), and it is working fine.

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


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

Don't use comparators <, >, ==, !=.
Use compare(_ other: Date) function.

Usage

// 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
}

For me the problem was that I had my own extension to Date class that was defining all the compare operators. Now (since swift 3) that Date is comparable, these extensions are not needed. So I commented them out and it worked.

SWIFT 3: Don't know if this is what you're looking for. But I compare a string to a current timestamp to see if my string is older that now.

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
}
}

To use it:

if (checkTimeStamp(date:"2016-11-21 12:00:00") == false) {
// Do something
}

from Swift 3 and above, Date is Comparable so we can directly compare dates like

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)

Alternatively We can create extension on 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
}
}

Use: let isEqual = date1.isEqualTo(date2)

Date is Comparable & Equatable (as of Swift 3)

This answer complements @Ankit Thakur's answer.

Since Swift 3 the Date struct (based on the underlying NSDate class) adopts the Comparable and Equatable protocols.

  • Comparable requires that Date implement the operators: <, <=, >, >=.
  • Equatable requires that Date implement the == operator.
  • Equatable allows Date to use the default implementation of the != operator (which is the inverse of the Equatable == operator implementation).

The following sample code exercises these comparison operators and confirms which comparisons are true with print statements.

Comparison function

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: ",  ")
}

Sample Use

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

To compare date only with year - month - day and without time for me worked like this:

     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)")
}

As of the time of this writing, Swift natively supports comparing Dates with all comparison operators (i.e. <, <=, ==, >=, and >). You can also compare optional Dates but are limited to <, ==, and >. If you need to compare two optional dates using <= or >=, i.e.

let date1: Date? = ...
let date2: Date? = ...
if date1 >= date2 { ... }

You can overload the <= and >=operators to support optionals:

func <= <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
return lhs == rhs || lhs < rhs
}


func >= <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
return lhs == rhs || lhs > rhs
}
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) }

Another way to do it:

    switch date1.compare(date2) {
case .orderedAscending:
break


case .orderedDescending:
break;


case .orderedSame:
break
}
   var strDateValidate = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"


let firstDate = dateFormatter.date(from:lblStartTime.text!)
let secondDate = dateFormatter.date(from:lblEndTime.text!)


if firstDate?.compare(secondDate!) == .orderedSame || firstDate?.compare(secondDate!) == .orderedAscending {
print("Both dates are same or first is less than scecond")
strDateValidate = "yes"
}
else
{
//second date is bigger than first
strDateValidate = "no"
}


if strDateValidate == "no"
{
alertView(message: "Start date and end date for a booking must be equal or Start date must be smaller than the end date", controller: self)
}

Swift 5:

1) If you use Date type:

let firstDate  = Date()
let secondDate = Date()


print(firstDate > secondDate)
print(firstDate < secondDate)
print(firstDate == secondDate)

2) If you use String type:

let firstStringDate  = "2019-05-22T09:56:00.1111111"
let secondStringDate = "2019-05-22T09:56:00.2222222"


print(firstStringDate > secondStringDate)  // false
print(firstStringDate < secondStringDate)  // true
print(firstStringDate == secondStringDate) // false

I'm not sure or the second option works at 100%. But how much would I not change the values of firstStringDate and secondStringDate the result was correct.

in Swift 3,4 you should use "Compare". for example:

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }

If you want to ignore seconds for example you can use

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

Example compare if it's the same day:

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