Comparación de NSDates sin componente de tiempo

En un parque infantil rápido, he estado usando

NSDate.date() 

Pero, esto siempre aparece con el elemento de tiempo anexado. Para mi aplicación, necesito ignorar el elemento de tiempo. ¿Es esto posible en Swift? ¿Cómo puede hacerse esto? Incluso si pudiera configurar el elemento de tiempo para que sea el mismo en todas las fechas, también funcionaría.

Además, estoy tratando de comparar dos fechas y en este momento estoy usando el siguiente código:

 var earlierDate:NSDate = firstDate.earlierDate(secondDate) 

¿Es esta la única manera o puedo hacer esto de una manera que ignore el elemento de tiempo? Por ejemplo, no quiero un resultado si son el mismo día, pero diferentes veces.

Use esta función NSCalendar para comparar fechas en iOS 8.0+

 func compareDate(date1: NSDate, toDate date2: NSDate, toUnitGranularity unit: NSCalendarUnit) -> NSComparisonResult 

pasar .Day como la unidad

Use esta función de la siguiente manera:

 let now = NSDate() // "Sep 23, 2015, 10:26 AM" let olderDate = NSDate(timeIntervalSinceNow: -10000) // "Sep 23, 2015, 7:40 AM" var order = NSCalendar.currentCalendar().compareDate(now, toDate: olderDate, toUnitGranularity: .Hour) switch order { case .OrderedDescending: print("DESCENDING") case .OrderedAscending: print("ASCENDING") case .OrderedSame: print("SAME") } // Compare to hour: DESCENDING order = NSCalendar.currentCalendar().compareDate(now, toDate: olderDate, toUnitGranularity: .Day) switch order { case .OrderedDescending: print("DESCENDING") case .OrderedAscending: print("ASCENDING") case .OrderedSame: print("SAME") } // Compare to day: SAME 

Hay varios métodos útiles en NSCalendar en iOS 8.0+:

 startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow 

E incluso para comparar días:

 func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool 

Para ignorar el elemento de tiempo, puede usar esto:

 var toDay = NSCalendar.currentCalendar().startOfDayForDate(NSDate()) 

Pero, si tiene que admitir también iOS 7, siempre puede escribir una extensión

 extension NSCalendar { func myStartOfDayForDate(date: NSDate!) -> NSDate! { let systemVersion:NSString = UIDevice.currentDevice().systemVersion if systemVersion.floatValue >= 8.0 { return self.startOfDayForDate(date) } else { return self.dateFromComponents(self.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date)) } } } 

Escribí el siguiente método para comparar dos fechas tomando prestado de la solución de Ashley Mills. Compara dos fechas y devuelve verdadero si las dos fechas son iguales (sin tiempo).

 func compareDate(date1:NSDate, date2:NSDate) -> Bool { let order = NSCalendar.currentCalendar().compareDate(date1, toDate: date2, toUnitGranularity: .Day) switch order { case .OrderedSame: return true default: return false } } 

Y se llama así:

 if compareDate(today, date2: anotherDate) { // The two dates are on the same day. } 

Comparaciones de dos fechas en rápido.

  // Date comparision to compare current date and end date. var dateComparisionResult:NSComparisonResult = currentDate.compare(endDate) if dateComparisionResult == NSComparisonResult.OrderedAscending { // Current date is smaller than end date. } else if dateComparisionResult == NSComparisonResult.OrderedDescending { // Current date is greater than end date. } else if dateComparisionResult == NSComparisonResult.OrderedSame { // Current date and end date are same. } 

En Swift 4:

 func compareDate(date1:Date, date2:Date) -> Bool { let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day) switch order { case .orderedSame: return true default: return false } } 

Para iOS7 soporte

 let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let date1String = dateFormatter.stringFromDate(date1) let date2String = dateFormatter.stringFromDate(date2) if date1String == date2String { println("Equal date") } 

Puede comparar dos fechas usando su descripción.

 let date1 = NSDate() let date2 = NSDate(timeIntervalSinceNow: 120) if date1.description == date2.description { print(true) } else { print(false) // false (I have added 2 seconds between them) } 

Si desea establecer el elemento de tiempo de sus fechas en un horario diferente, puede hacer lo siguiente:

 extension NSDate { struct Calendar { static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)! } var day: Int { return Calendar.gregorian.component(.Day, fromDate: self) } var month: Int { return Calendar.gregorian.component(.Month, fromDate: self) } var year: Int { return Calendar.gregorian.component(.Year, fromDate: self) } var noon: NSDate { return Calendar.gregorian.dateWithEra(1, year: year, month: month, day: day, hour: 12, minute: 0, second: 0, nanosecond: 0)! } } let date1 = NSDate() let date2 = NSDate(timeIntervalSinceNow: 120) print(date1.noon == date2.noon) // true 

o también puedes hacerlo usando NSDateFormatter:

 extension NSDate { struct Date { static let formatterYYYYMMDD: NSDateFormatter = { let formatter = NSDateFormatter() formatter.dateFormat = "yyyyMMdd" return formatter }() } var yearMonthDay: String { return Date.formatterYYYYMMDD.stringFromDate(self) } func isSameDayAs(date:NSDate) -> Bool { return yearMonthDay == date.yearMonthDay } } let date1 = NSDate() let date2 = NSDate(timeIntervalSinceNow: 120) print(date1.yearMonthDay == date2.yearMonthDay) // true print(date1.isSameDayAs(date2)) // true 

Otra opción (iOS8 +) es usar el método de calendario isDate (inSameDayAsDate :):

 extension NSDate { struct Calendar { static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)! } func isInSameDayAs(date date: NSDate) -> Bool { return Calendar.gregorian.isDate(self, inSameDayAsDate: date) } } let date1 = NSDate() let date2 = NSDate(timeIntervalSinceNow: 120) if date1.isInSameDayAs(date: date2 ){ print(true) // true } else { print(false) } 

Para Swift3

 var order = NSCalendar.current.compare(firstDate, to: secondDate, toGranularity: .hour) if order == .orderedSame { //Both the dates are same. //Your Logic. } 

Swift 3

  let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day) if order == .orderedAscending { // date 1 is older } else if order == .orderedDescending { // date 1 is newer } else if order == .orderedSame { // same day/hour depending on granularity parameter } 

Escribí una extensión de Swift 4 para comparar dos fechas:

 import Foundation extension Date { func isSameDate(_ comparisonDate: Date) -> Bool { let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day) return order == .orderedSame } func isBeforeDate(_ comparisonDate: Date) -> Bool { let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day) return order == .orderedAscending } func isAfterDate(_ comparisonDate: Date) -> Bool { let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day) return order == .orderedDescending } } 

Uso:

startDate.isSameDateAs(endDate) // returns a true or false

Rápido:

 extension NSDate { /** Compares current date with the given one down to the seconds. If date==nil, then always return false :param: date date to compare or nil :returns: true if the dates has equal years, months, days, hours, minutes and seconds. */ func sameDate(date: NSDate?) -> Bool { if let d = date { let calendar = NSCalendar.currentCalendar() if NSComparisonResult.OrderedSame == calendar.compareDate(self, toDate: d, toUnitGranularity: NSCalendarUnit.SecondCalendarUnit) { return true } } return false } } 

Cuando NSDate.date() en el patio de recreo, verá la descripción predeterminada impresa. Use NSDateFormatter para imprimir una descripción localizada del objeto de fecha, posiblemente solo con la porción de fecha.

Para poner a cero partes específicas de una fecha (para fines de comparación), use NSDateComponents junto con NSCalendar .

En mi experiencia, la mayoría de los problemas de las personas al usar NSDate proviene de la suposición incorrecta de que un NSDate puede usarse para representar una fecha en el sentido “normal” (es decir, un período de 24 comenzando a la medianoche en la zona horaria local). En el uso normal (todos los días / sin progtwigción), el 1 de enero de 2014 en Londres es la misma fecha que el 1 de enero en Beijing o Nueva York , aunque cubren diferentes períodos en tiempo real . Para llevar esto al extremo, el tiempo en Christmas Island es UTC + 14 mientras que el tiempo en Midway Island es UTC-11. Por lo tanto, el 1 de enero de 2014 en estas dos islas tiene la misma fecha, a pesar de que uno ni siquiera comienza hasta que el otro se haya completado durante una hora.

Si ese es el tipo de fecha que está grabando (y si no está grabando el componente de tiempo, probablemente lo es), entonces no use NSDate (que almacena solo segundos después de 2001-01-01 00:00 UTC, nada más) pero almacene el año mes y día como números enteros, tal vez creando su propia clase CivilDate que ajuste estos valores, y use eso en su lugar.

Solo ingrese en NSDate para comparar fechas y luego asegúrese de declarar explícitamente la zona horaria como “UTC” en ambos NSDates para fines de comparación.

Swift iOS 8 en adelante Cuando necesita más que simples comparaciones de fechas más grandes o más pequeñas. Por ejemplo, es el mismo día o el día anterior, …

 extension Date { func compareTo(date: Date, toGranularity: Calendar.Component ) -> ComparisonResult { var cal = Calendar.current cal.timeZone = TimeZone(identifier: "Europe/Paris")! return cal.compare(self, to: date, toGranularity: toGranularity) } } 

Por ejemplo, cómo usar esto en un filtro, vea esta respuesta:

https://stackoverflow.com/a/45746206/4946476

 // Get current date let dateA = NSDate() // Get a later date (after a couple of milliseconds) let dateB = NSDate() // 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") } 

Para responder tu pregunta:

¿Es esto posible en Swift?

Sí, es posible


Ahh, también quieres ahora CÓMO

 let cal = NSCalendar.currentCalendar() cal.rangeOfUnit(.DayCalendarUnit, startDate: &d1, interval: nil, forDate: d1) // d1 NSDate? cal.rangeOfUnit(.DayCalendarUnit, startDate: &d2, interval: nil, forDate: d2) // d2 NSDate? 

Ahora d1 y d2 contendrán las fechas al comienzo de sus días.

comparar con d1!.compare(d2!)

Para mostrarlos sin porción de tiempo, us NSDateFormatter.