Swift 3 - Vergleichen von Datumsobjekten

94

Ich aktualisiere meine App auf die Swift 3.0-Syntax (ich weiß, dass sie sich noch in der Beta befindet, aber ich möchte darauf vorbereitet sein, sobald sie veröffentlicht wird).

Bis zur vorherige Beta von Xcode (Beta 5) konnte ich zwei vergleichen DateObjekte mit den Operatoren <, >und ==. In der neuesten Beta (Beta 6) funktioniert dies jedoch nicht mehr. Hier einige Screenshots:

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Wie Sie in beiden Screenshots sehen können, sind dies zwei DateObjekte. Aber ich bekomme folgenden Fehler: Geben Sie hier die Bildbeschreibung ein

Was mache ich falsch? Die Funktionen sind weiterhin in der DateKlasse deklariert :

static func >(Date, Date)

Gibt true zurück, wenn das Datum auf der linken Seite später als das Datum auf der rechten Seite liegt.

Ist das nur ein Beta-Fehler oder mache ich etwas falsch?

beeef
quelle
2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }funktioniert in meinem Xcode 8 Beta 6.
Martin R
1
Ja. - Sie sollten die vollständige Fehlermeldung im Berichtsnavigator nachschlagen.
Martin R
Danke @MartinR! Ich wusste nicht, dass ich in einen Fehler "eintauchen" und mehr Informationen erhalten kann. Hat mir viel geholfen!
Beeef
Akzeptiere die richtige Antwort
Ankit Thakur

Antworten:

161

Ich habe dieses Snippet (in Xcode 8 Beta 6) ausprobiert und es funktioniert einwandfrei.

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

if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }
Ankit Thakur
quelle
wenn ich die Zeit ignorieren will. zB 2019-05-14 12:08:14 +0000== 2019-05-14sollte true zurückgeben. dann was ?
Awais Fayyaz
@AwaisFayyaz Wenn Sie Daten vergleichen möchten, ohne eine DateComponent zu berücksichtigen. Sie müssen die gewünschten Komponenten ab dem Datum erhalten. Holen Sie sich dann das Datum von DateComponents und vergleichen Sie sie.
Giorgio Doganiero
52

Dateist Comparable& Equatable(ab Swift 3)

Diese Antwort ergänzt die Antwort von @Ankit Thakur.

Seit Swift 3 übernimmt die DateStruktur (basierend auf der zugrunde liegenden NSDateKlasse) die Protokolle Comparableund Equatable.

  • Comparabledas erfordert Dateimplementieren die Betreiber: <, <=, >, >=.
  • Equatableerfordert, dass Dateder ==Operator implementiert .
  • EquatableErmöglicht Datedie Verwendung der Standardimplementierung des !=Operators (die Umkehrung der Equatable ==Operatorimplementierung).

Der folgende Beispielcode übt diese Vergleichsoperatoren aus und bestätigt, welche Vergleiche mit printAnweisungen wahr sind .

Vergleichsfunktion

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

Beispielgebrauch

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
Mobiler Dan
quelle
30

Ab Swift 3 und höher ist Datum vergleichbar, sodass wir Daten wie vergleichen können

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)

Alternativ können wir eine Erweiterung am Datum erstellen

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

Verwenden: let isEqual = date1.isEqualTo(date2)

Suhit Patil
quelle
wenn ich die Zeit ignorieren will. zB 2019-05-14 12:08:14 +0000== 2019-05-14sollte true zurückgeben. dann was ?
Awais Fayyaz
15

Schauen Sie sich diese http://iswift.org/cookbook/compare-2-dates an

Termine abrufen:

// Get current date
let dateA = NSDate()

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

Verwenden der SWITCH-Anweisung

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

mit IF-Anweisung

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

 //OR

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

 }
Luis Abreu Acevedo
quelle
9

Für mich war das Problem, dass ich eine eigene Erweiterung der Date-Klasse hatte, die alle Vergleichsoperatoren definierte. Jetzt (seit Swift 3) ist das Datum vergleichbar, diese Erweiterungen werden nicht benötigt. Also habe ich sie auskommentiert und es hat funktioniert.

Jitendra Kulkarni
quelle
7

SWIFT 3: Ich weiß nicht, ob Sie danach suchen. Aber ich vergleiche eine Zeichenfolge mit einem aktuellen Zeitstempel, um festzustellen, ob meine Zeichenfolge jetzt älter ist.

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

Um es zu benutzen:

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

Das Datum nur mit Jahr - Monat - Tag und ohne Zeit zu vergleichen, hat für mich so funktioniert:

     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)")
                        }
Alessandro Mattiuzzi
quelle
5

Wenn Sie beispielsweise Sekunden ignorieren möchten, können Sie verwenden

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

Beispiel vergleichen, wenn es am selben Tag ist:

Calendar.current.isDate(date1, equalTo: date2, toGranularity: .day)
zdravko zdravkin
quelle
1

Ab dem Zeitpunkt des Schreibens dieses Artikels, zu vergleichen Swift nativ unterstützt Termine mit allen Vergleichsoperatoren (dh <, <=, ==, >=, und >). Sie können auch optionale Daten vergleichen , sondern beschränken sich auf <, ==und >. Wenn Sie zwei optionale Daten mit <=oder vergleichen müssen >=, z

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

Sie können die Operatoren <=und überladen >=, um Optionen zu unterstützen:

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
}
NSExceptional
quelle
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) }
Arjun Patel
quelle
1

Ein anderer Weg, es zu tun:

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

        case .orderedDescending:
            break;

        case .orderedSame:
            break
    }
Shadros
quelle
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)
            }
Davender Verma
quelle
1

Swift 5:

1) Wenn Sie den Datumstyp verwenden:

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

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

2) Wenn Sie einen String-Typ verwenden:

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 

Ich bin nicht sicher oder die zweite Option funktioniert zu 100%. Aber wie sehr würde ich die Werte von firstStringDate und secondStringDate nicht ändern, das Ergebnis war korrekt.

Maxwell
quelle
1

In Swift 3,4 sollten Sie "Vergleichen" verwenden. beispielsweise:

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