Swift 3 - Comparación de objetos de fecha

94

Estoy actualizando mi aplicación a la sintaxis Swift 3.0 (sé que todavía está en versión beta, pero quiero estar preparado tan pronto como se publique).

Hasta que la Beta previa de Xcode (Beta 5) que era capaz de comparar dos Dateobjetos usando los operandos <, >y ==. Pero en la última versión beta (Beta 6) esto ya no funciona. A continuación se muestran algunas capturas de pantalla:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Como puede ver en ambas capturas de pantalla, estos son dos Dateobjetos. Pero obtengo el siguiente error: ingrese la descripción de la imagen aquí

¿Qué estoy haciendo mal? Las funciones todavía están declaradas en la Dateclase:

static func >(Date, Date)

Devuelve verdadero si la fecha de la izquierda es posterior en el tiempo que la fecha de la derecha.

¿Es esto solo un error Beta o estoy haciendo algo mal?

Beeef
fuente
2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }funciona en mi Xcode 8 beta 6.
Martin R
1
Si. - Debería buscar el mensaje de error completo en el navegador de informes.
Martin R
¡Gracias @MartinR! No sabía que puedo "sumergirme" en un error y obtener más información. ¡Me ayudo mucho!
Beeef
aceptar la respuesta correcta
Ankit Thakur

Respuestas:

161

Probé este fragmento (en Xcode 8 Beta 6) y está funcionando bien.

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

if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }
Ankit Thakur
fuente
si quiero ignorar el tiempo. por ejemplo, 2019-05-14 12:08:14 +0000== 2019-05-14debería devolver verdadero. y que ?
Awais Fayyaz
@AwaisFayyaz Si desea comparar fechas sin tener en cuenta un DateComponent. Debe obtener los componentes que desee a partir de la fecha. Luego obtenga la fecha de DateComponents y compárelos.
Giorgio Doganiero
52

Datees Comparable& Equatable(a partir de Swift 3)

Esta respuesta complementa la respuesta de @Ankit Thakur.

Desde Swift 3, la Dateestructura (basada en la NSDateclase subyacente ) adopta los protocolos Comparabley Equatable.

  • Comparablerequiere que Dateimplementan los operadores: <, <=, >, >=.
  • EquatableRequiere que Dateimplemente el ==operador.
  • Equatablepermite Dateutilizar la implementación predeterminada del !=operador (que es la inversa de la Equatable ==implementación del operador).

El siguiente código de muestra ejercita estos operadores de comparación y confirma qué comparaciones son verdaderas con printdeclaraciones.

Función de comparación

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 de muestra

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
Dan móvil
fuente
31

de Swift 3 y superior, la fecha es comparable, por lo que podemos comparar directamente fechas como

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)

Alternativamente, podemos crear una extensión en la fecha

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

Utilizar: let isEqual = date1.isEqualTo(date2)

Suhit Patil
fuente
si quiero ignorar el tiempo. por ejemplo, 2019-05-14 12:08:14 +0000== 2019-05-14debería devolver verdadero. y que ?
Awais Fayyaz
15

Mira esto http://iswift.org/cookbook/compare-2-dates

Obtener fechas:

// Get current date
let dateA = NSDate()

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

Uso de la instrucción 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")
}

usando la instrucción IF

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

 //OR

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

 }
Luis Abreu Acevedo
fuente
9

Para mí, el problema era que tenía mi propia extensión para la clase Date que definía todos los operadores de comparación. Ahora (desde swift 3) que Date es comparable, estas extensiones no son necesarias. Así que los comenté y funcionó.

Jitendra Kulkarni
fuente
7

SWIFT 3: No sé si esto es lo que estás buscando. Pero comparo una cadena con una marca de tiempo actual para ver si mi cadena es más antigua que ahora.

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

Para usarlo:

if (checkTimeStamp(date:"2016-11-21 12:00:00") == false) {
    // Do something
}
nótese bien
fuente
5

Para comparar la fecha solo con el año - mes - día y sin tiempo para mí funcionó así:

     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
fuente
5

Si desea ignorar los segundos, por ejemplo, puede usar

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

Ejemplo compare si es el mismo día:

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

En el momento de este escrito, Swift soportes de forma nativa la comparación de fechas con todos los operadores de comparación (es decir <, <=, ==, >=, y >). También puede comparar fechas opcionales, pero se limitan a <, ==, y >. Si necesita comparar dos fechas opcionales usando <=o >=, es decir

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

Puede sobrecargar los operadores <=y >=para admitir opciones:

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
}
NS Excepcional
fuente
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
fuente
1

Otra forma de hacerlo:

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

        case .orderedDescending:
            break;

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

Rápido 5:

1) Si usa el tipo de fecha:

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

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

2) Si usa el tipo de cadena:

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 

No estoy seguro o la segunda opción funciona al 100%. Pero, ¿cuánto no cambiaría los valores de firstStringDate y secondStringDate? El resultado fue correcto.

Maxwell
fuente
1

en Swift 3,4 debe usar "Comparar". por ejemplo:

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