Swift 3 - Порівняння об'єктів Date


95

Я оновлюю свій додаток до синтаксису Swift 3.0 (я знаю, що він все ще в бета-версії, але я хочу бути готовим, як тільки він вийде).

До попередньої бета-версії Xcode (Beta 5) я міг порівнювати два Dateоб'єкти, використовуючи операнди <, >і ==. Але в останній бета-версії (Beta 6) це вже не працює. Ось кілька знімків екрану:

введіть тут опис зображення введіть тут опис зображення

Як ви можете бачити на обох знімках екрана, це два Dateоб'єкти. Але я отримую таку помилку: введіть тут опис зображення

Що я роблю неправильно? Функції все ще оголошені в Dateкласі:

static func >(Date, Date)

Повертає true, якщо дата лівої руки пізніше, ніж дата правої руки.

Це лише бета-помилка чи я роблю щось не так?


2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }працює в моєму Xcode 8 beta 6.
Martin R

1
Так. - Ви повинні переглянути повне повідомлення про помилку в навігаторі звітів.
Martin R

Дякую @MartinR! Не знав, що я можу "зануритися" у помилку та отримати більше інформації. Мені дуже допомогло!
beeef

прийміть правильну відповідь
Ankit Thakur

Відповіді:


161

Я спробував цей фрагмент (у 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,

@AwaisFayyaz Якщо ви хочете порівняти дати, не беручи до уваги компонент DateComponent. Вам потрібно отримати потрібні компоненти з дати. Потім отримайте дату з DateComponents і порівняйте їх.
Джорджо Доганьєро

52

Dateє Comparable& Equatable(станом на Swift 3)

Ця відповідь доповнює відповідь @Ankit Thakur.

Починаючи з Swift 3, Dateструктура (заснована на базовому NSDateкласі) приймає протоколи Comparableand Equatable.

  • 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

31

від Swift 3 і вище, Дата порівняльна, тому ми можемо безпосередньо порівнювати такі дати

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)

Як варіант, ми можемо створити розширення на дату

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)


якщо я хочу ігнорувати час. наприклад 2019-05-14 12:08:14 +0000== 2019-05-14має повернути true. тоді що ?
Awais Fayyaz,

15

Дивіться цей http://iswift.org/cookbook/compare-2-dates

Отримати дати:

// Get current date
let dateA = NSDate()

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

Використання заяви SWITCH

// Compare them
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")
}

за допомогою твердження IF

 if dateA.compare(dateB) == .orderedAscending {
     datePickerTo.date = datePicker.date
 }

 //OR

 if case .orderedAcending = dateA.compare(dateB) {

 }

9

Для мене проблема полягала в тому, що я мав власне розширення до класу Date, яке визначало всі оператори порівняння. Тепер (з швидкого 3) ця дата порівнянна, ці розширення не потрібні. Тому я їх прокоментував, і це спрацювало.


7

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
}

5

Для порівняння дати лише з роком - місяцем - днем ​​і без часу для мене працювали так:

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

5

Наприклад, якщо ви хочете ігнорувати секунди, ви можете використовувати

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

Приклад порівняння, якщо це того ж дня:

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

1

Станом на момент написання цієї статті, Swift спочатку підтримує порівняння дат з усіма операторами порівняння (тобто <, <=, ==, >=, і >). Ви можете також порівняти додаткові дати , але обмежені <, ==і >. Якщо вам потрібно порівняти дві необов’язкові дати, використовуючи <=або >=, тобто

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

Ви можете перевантажити оператори <=та, >=щоб підтримати додаткові:

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
}

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
    }

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

1

Свіфт 5:

1) Якщо ви використовуєте тип дати:

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

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

2) Якщо ви використовуєте тип рядка:

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 

Я не впевнений, або другий варіант працює на 100%. Але скільки б я не змінив значення firstStringDate і secondStringDate, результат був правильним.


1

у Swift 3,4 ви повинні використовувати "Порівняти". наприклад:

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.