Swift 3 - Comparaison des objets Date

95

Je mets à jour mon application à la syntaxe Swift 3.0 (je sais qu'elle est toujours en version bêta mais je veux être préparé dès sa sortie).

Jusqu'à la précédente version bêta de Xcode (bêta 5), ​​je pouvais comparer deux Dateobjets en utilisant les opérandes <, >et ==. Mais dans la dernière version bêta (bêta 6), cela ne fonctionne plus. Voici quelques captures d'écran:

entrez la description de l'image ici entrez la description de l'image ici

Comme vous pouvez le voir sur les deux captures d'écran, ce sont deux Dateobjets. Mais j'obtiens l'erreur suivante: entrez la description de l'image ici

Qu'est-ce que je fais mal? Les fonctions sont toujours déclarées dans la Dateclasse:

static func >(Date, Date)

Renvoie vrai si la date de gauche est postérieure à la date de droite.

Est-ce juste un bug bêta ou est-ce que je fais quelque chose de mal?

abeille
la source
2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }fonctionne dans mon Xcode 8 beta 6.
Martin R
1
Oui. - Vous devez rechercher le message d'erreur complet dans le navigateur de rapports.
Martin R
Merci @MartinR! Je ne savais pas que je pouvais "plonger" dans une erreur et obtenir plus d'informations. M'a beaucoup aidé!
beeef
accepter la bonne réponse
Ankit Thakur

Réponses:

161

J'ai essayé cet extrait (dans Xcode 8 Beta 6), et cela fonctionne très bien.

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

if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }
Ankit Thakur
la source
si je veux ignorer le temps. par exemple 2019-05-14 12:08:14 +0000== 2019-05-14devrait retourner true. alors quoi?
Awais Fayyaz
@AwaisFayyaz Si vous souhaitez comparer des dates sans prendre en compte un DateComponent. Vous devez obtenir les composants souhaités à partir de la date. Ensuite, récupérez la date de DateComponents et comparez-les.
Giorgio Doganiero
52

Dateis Comparable& Equatable(à partir de Swift 3)

Cette réponse complète la réponse de @Ankit Thakur.

Depuis Swift 3, la Datestructure (basée sur la NSDateclasse sous-jacente ) adopte les protocoles Comparableet Equatable.

  • Comparableexige que Datemettre en œuvre les opérateurs: <, <=, >, >=.
  • Equatablenécessite que Datemettre en œuvre l' ==opérateur.
  • Equatablepermet Dated'utiliser l'implémentation par défaut de l' !=opérateur (qui est l'inverse de l' Equatable ==implémentation de l' opérateur).

L'exemple de code suivant exerce ces opérateurs de comparaison et confirme quelles comparaisons sont vraies avec des printinstructions.

Fonction de comparaison

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

Exemple d'utilisation

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
Mobile Dan
la source
31

à partir de Swift 3 et supérieur, la date est comparable afin que nous puissions comparer directement des dates telles que

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)

Alternativement, nous pouvons créer une extension sur 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
  }
}

Utilisation: let isEqual = date1.isEqualTo(date2)

Suhit Patil
la source
si je veux ignorer le temps. par exemple 2019-05-14 12:08:14 +0000== 2019-05-14devrait retourner true. alors quoi?
Awais Fayyaz
15

Regardez ceci http://iswift.org/cookbook/compare-2-dates

Obtenir des dates:

// Get current date
let dateA = NSDate()

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

Utilisation de l'instruction 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")
}

utilisation de l'instruction IF

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

 //OR

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

 }
Luis Abreu Acevedo
la source
9

Pour moi, le problème était que j'avais ma propre extension à la classe Date qui définissait tous les opérateurs de comparaison. Maintenant (depuis swift 3) que Date est comparable, ces extensions ne sont plus nécessaires. Alors je les ai commentés et ça a marché.

Jitendra Kulkarni
la source
7

SWIFT 3: Je ne sais pas si c'est ce que vous recherchez. Mais je compare une chaîne à un horodatage actuel pour voir si ma chaîne est plus ancienne que maintenant.

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

Pour l'utiliser:

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

Pour comparer la date uniquement avec année - mois - jour et sans heure pour moi a fonctionné comme ceci:

     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
la source
5

Si vous voulez ignorer les secondes par exemple, vous pouvez utiliser

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

Exemple de comparaison si c'est le même jour:

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

Au moment d'écrire ces lignes, Swift prend nativement en charge la comparaison des dates avec tous les opérateurs de comparaison (c. -à <, <=, ==, >=et >). Vous pouvez également comparer les dates en option mais sont limités <, ==et >. Si vous avez besoin de comparer deux dates facultatives en utilisant <=ou >=, ie

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

Vous pouvez surcharger les opérateurs <=et >=pour prendre en charge les options:

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
}
NSExceptionnel
la source
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
la source
1

Une autre façon de le faire:

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

        case .orderedDescending:
            break;

        case .orderedSame:
            break
    }
Shadros
la source
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
la source
1

Swift 5:

1) Si vous utilisez le type de date:

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

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

2) Si vous utilisez le type 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 

Je ne suis pas sûr ou la deuxième option fonctionne à 100%. Mais à quel point je ne changerais pas les valeurs de firstStringDate et secondStringDate, le résultat était correct.

Maxwell
la source
1

dans Swift 3,4, vous devez utiliser "Compare". par exemple:

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