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?


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

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

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)


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) {

 }

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ó.


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
}

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

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)

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
}

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

Otra forma de hacerlo:

    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

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.


1

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

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.