Swift 3 - Comparing Date objects

IosXcodeSwift3Beta

Ios Problem Overview


I'm updating my app to Swift 3.0 syntax (I know it's still in beta but I want to be prepared as soon as it released).

Until the previous Beta of Xcode (Beta 5) I was able to compare two Date objects using the operands <, > and ==. But in the latest beta (Beta 6) this isn't working any more. Here are some screenshots:

enter image description here enter image description here

As you can see in both screenshots, these are two Date objects. But I get the following error: enter image description here

What am I doing wrong? The functions are still declared in the Date class:

> static func >(Date, Date) > >>Returns true if the left hand Date is later in time than the right hand Date.

Is this just a Beta bug or am I doing something wrong?

Ios Solutions


Solution 1 - Ios

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

Solution 2 - Ios

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

Solution 3 - Ios

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)

Solution 4 - Ios

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
}

Solution 5 - Ios

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.

Solution 6 - Ios

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
}

Solution 7 - Ios

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)

Solution 8 - Ios

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

Solution 9 - Ios

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
}

Solution 10 - Ios

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

Solution 11 - Ios

Another way to do it:

    switch date1.compare(date2) {
        case .orderedAscending:
            break
        
        case .orderedDescending:
            break;
        
        case .orderedSame:
            break
    }

Solution 12 - Ios

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

Solution 13 - Ios

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.

Solution 14 - Ios

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbeeefView Question on Stackoverflow
Solution 1 - IosAnkit ThakurView Answer on Stackoverflow
Solution 2 - IosMobile DanView Answer on Stackoverflow
Solution 3 - IosSuhit PatilView Answer on Stackoverflow
Solution 4 - IosLuis Abreu AcevedoView Answer on Stackoverflow
Solution 5 - IosJitendra KulkarniView Answer on Stackoverflow
Solution 6 - IosN.BView Answer on Stackoverflow
Solution 7 - Ioszdravko zdravkinView Answer on Stackoverflow
Solution 8 - IosAlessandro MattiuzziView Answer on Stackoverflow
Solution 9 - IosNSExceptionalView Answer on Stackoverflow
Solution 10 - IosArjun PatelView Answer on Stackoverflow
Solution 11 - IosShadrosView Answer on Stackoverflow
Solution 12 - IosDavender VermaView Answer on Stackoverflow
Solution 13 - IosmaxwellView Answer on Stackoverflow
Solution 14 - IosAlirezaView Answer on Stackoverflow