Swift 3 - Confronto degli oggetti Data


95

Sto aggiornando la mia app alla sintassi Swift 3.0 (so che è ancora in beta ma voglio essere preparato non appena viene rilasciata).

Fino alla precedente Beta di Xcode (Beta 5) ero in grado di confrontare due Dateoggetti usando gli operandi <, >e ==. Ma nell'ultima beta (Beta 6) questo non funziona più. Ecco alcuni screenshot:

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Come puoi vedere in entrambi gli screenshot, questi sono due Dateoggetti. Ma ottengo il seguente errore: inserisci qui la descrizione dell'immagine

Che cosa sto facendo di sbagliato? Le funzioni sono ancora dichiarate nella Dateclasse:

static func >(Date, Date)

Restituisce vero se la data della mano sinistra è successiva nel tempo rispetto alla data della mano destra.

È solo un bug della beta o sto facendo qualcosa di sbagliato?


2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }funziona nel mio Xcode 8 beta 6.
Martin R

1
Sì. - È necessario cercare il messaggio di errore completo nel navigatore report.
Martin R

Grazie @MartinR! Non sapevo di poter "tuffarmi" in un errore e ottenere maggiori informazioni. Mi ha aiutato molto!
beeef

accetta la risposta corretta
Ankit Thakur

Risposte:


161

Ho provato questo frammento (in Xcode 8 Beta 6) e funziona bene.

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

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

se voglio ignorare il tempo. ad esempio 2019-05-14 12:08:14 +0000== 2019-05-14dovrebbe restituire true. allora cosa?
Awais Fayyaz

@AwaisFayyaz Se desideri confrontare le date senza prendere in considerazione DateComponent. È necessario ottenere i componenti desiderati dalla data. Quindi ottenere la data da DateComponents e confrontarli.
Giorgio Doganiero

52

Dateè Comparable& Equatable(a partire da Swift 3)

Questa risposta completa la risposta di @Ankit Thakur.

A partire da Swift 3, la Datestruttura (basata sulla NSDateclasse sottostante ) adotta i protocolli Comparablee Equatable.

  • Comparablerichiede che Dateimplementano gli operatori: <, <=, >, >=.
  • Equatablerichiede che Dateimplementa l' ==operatore.
  • Equatableconsente Datedi utilizzare l'implementazione predefinita !=dell'operatore (che è l'inverso dell'implementazione Equatable ==dell'operatore).

Il codice di esempio seguente esercita questi operatori di confronto e conferma quali confronti sono veri con le printistruzioni.

Funzione di confronto

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

Uso del campione

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

da Swift 3 e versioni successive, la data è comparabile in modo da poter confrontare direttamente date come

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)

In alternativa possiamo creare l'estensione in data

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

Uso: let isEqual = date1.isEqualTo(date2)


se voglio ignorare il tempo. ad esempio 2019-05-14 12:08:14 +0000== 2019-05-14dovrebbe restituire true. allora cosa?
Awais Fayyaz

15

Guarda questo http://iswift.org/cookbook/compare-2-dates

Ottieni date:

// Get current date
let dateA = NSDate()

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

Utilizzo dell'istruzione 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")
}

utilizzando l'istruzione IF

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

 //OR

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

 }

9

Per me il problema era che avevo la mia estensione alla classe Date che definiva tutti gli operatori di confronto. Ora (poiché Swift 3) quella Data è comparabile, queste estensioni non sono necessarie. Quindi li ho commentati e ha funzionato.


7

SWIFT 3: Non so se questo è quello che stai cercando. Ma confronto una stringa con un timestamp corrente per vedere se la mia stringa è più vecchia di adesso.

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

Per usarlo:

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

5

Per confrontare la data solo con anno - mese - giorno e senza tempo per me ha funzionato in questo modo:

     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

Se vuoi ignorare i secondi, ad esempio, puoi usare

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

Esempio di confronto se è lo stesso giorno:

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

1

A partire dal momento in cui scriviamo, Swift supporta nativamente confrontando date con tutti gli operatori di confronto (cioè <, <=, ==, >=, e >). È inoltre possibile confrontare le date a richiesta, ma sono limitati a <, ==e >. Se è necessario confrontare due date opzionali utilizzando <=o >=, ad es

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

Puoi sovraccaricare gli operatori <=e >=per supportare gli optional:

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

Un altro modo per farlo:

    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

Swift 5:

1) Se utilizzi il tipo di data:

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

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

2) Se utilizzi il tipo String:

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 

Non sono sicuro o la seconda opzione funziona al 100%. Ma quanto non cambierei i valori di firstStringDate e secondStringDate il risultato era corretto.


1

in Swift 3,4 dovresti usare "Confronta". per esempio:

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.