ios - Comparación de NSDates sin componente de tiempo
time swift (16)
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 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.
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 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
}
}
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 programació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.
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.
}
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
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))
}
}
}
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")
}
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.
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
}
}
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
Para Swift3
var order = NSCalendar.current.compare(firstDate, to: secondDate, toGranularity: .hour)
if order == .orderedSame {
//Both the dates are same.
//Your Logic.
}
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)
}
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
}
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://.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")
}