Сравнение двух NSDates и игнорирование временной составляющей

Каков наиболее эффективный / рекомендуемый способ сравнения двух NSDate? Я хотел бы видеть, есть ли обе даты в тот же день, независимо от времени, и начали писать код, который использует метод timeIntervalSinceDate: внутри classа NSDate и получает целое число этого значения, деленное на количество секунд в день. Это кажется длинным, и я чувствую, что мне не хватает чего-то очевидного.

Код, который я пытаюсь исправить:

if (!([key compare:todaysDate] == NSOrderedDescending)) { todaysDateSection = [eventSectionsArray count] - 1; } 

где key и todaysDate являются объектами NSDate, а todaysDate создает с использованием:

 NSDate *todaysDate = [[NSDate alloc] init]; 

С уважением

Дейв

Вы устанавливаете время в день до 00:00:00 перед выполнением сравнения:

 unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay; NSCalendar* calendar = [NSCalendar currentCalendar]; NSDateComponents* components = [calendar components:flags fromDate:date]; NSDate* dateOnly = [calendar dateFromComponents:components]; // ... necessary cleanup 

Затем вы можете сравнить значения даты. См. Обзор в справочной документации .

Я удивлен, что никакие другие ответы не имеют этой опции для получения даты «начала дня» для объектов:

 [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1]; [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2]; 

Что устанавливает date1 и date1 в начале их соответствующих дней. Если они равны, они находятся в один день.

Или этот вариант:

 NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1]; NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2]; 

Который задает day1 и day2 несколько произвольным значениям, которые можно сравнить. Если они равны, они находятся в один день.

Существует новый метод, который был введен в NSCalendar с iOS 8, что делает это намного проще.

 - (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0); 

Вы устанавливаете зернистость в единицах (единицах), которые имеют значение. Это игнорирует все другие единицы и пределы, сравнимые с выбранными.

Для iOS8 и более поздних версий проверка того, что две даты происходят в тот же день, проста:

 [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] 

См. Документацию

Это краткое изложение всех ответов:

 NSInteger interval = [[[NSCalendar currentCalendar] components: NSDayCalendarUnit fromDate: date1 toDate: date2 options: 0] day]; if(interval<0){ //date10){ //date2 

Я использовал подход Duncan C, я исправил некоторые ошибки, которые он сделал

 -(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate { NSCalendar *currentCalendar = [NSCalendar currentCalendar]; NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0]; NSInteger days = [components day]; return days; } 

Я использую этот небольшой метод использования:

 -(NSDate*)normalizedDateWithDate:(NSDate*)date { NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate: date]; return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized } 

(Вам, очевидно, нужно иметь ivar, называемый calendar_ содержащий NSCalendar .)

Используя это, легко проверить, существует ли сегодня такая дата:

 [[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]]; 

( [NSDate date] возвращает текущую дату и время.)

Это, конечно, очень похоже на то, что предлагает Грегори. Недостатком этого подхода является то, что он имеет тенденцию создавать множество временных объектов NSDate . Если вы собираетесь обрабатывать множество дат, я бы рекомендовал использовать какой-либо другой метод, например, напрямую сравнивать компоненты или работать с объектами NSDateComponents вместо NSDates .

Ответ проще, чем все делают это. NSCalendar имеет метод

 components:fromDate:toDate:options 

Этот метод позволяет рассчитать разницу между двумя датами, используя любые единицы, которые вы хотите.

Поэтому напишите такой метод:

 -(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate) { NSCalendar *currentCalendar = [NSCalendar currentCalendar]; NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0]; NSInteger days = [components days]; return days; } 

Если указанный выше метод возвращает ноль, две даты относятся к одному и тому же дню.

Начиная с iOS 8.0, вы можете использовать:

 NSCalendar *calendar = [NSCalendar currentCalendar]; NSComparisonResult dateComparison = [calendar compareDate:[NSDate date] toDate:otherNSDate toUnitGranularity:NSCalendarUnitDay]; 

Если результатом является, например, NSOrderedDescending, otherDate до [NSDate date] с точки зрения дней.

Я не вижу этот метод в документации NSCalendar, но он находится в iOS 7.1 для iOS 8.0. Различия API

Для разработчиков, кодирующих в Swift 3

 if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){ // Do something } 
 int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24); if (interval!=0){ //not the same day; } 

моим решением было два преобразования с NSDateFormatter:

  NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyyMMdd"]; [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0]; NSString *todayString=[dateFormat stringFromDate:today]; NSDate *todayWithoutHour=[dateFormat dateFromString:todayString]; if ([today compare:exprDate] == NSOrderedDescending) { //do } 

С Swift 3, в соответствии с вашими потребностями, вы можете выбрать один из двух следующих шаблонов, чтобы решить вашу проблему.


# 1. Использование метода compare(_:to:toGranularity:)

Calendar есть метод, называемый compare(_:​to:​to​Granularity:​) . compare(_:​to:​to​Granularity:​) имеет следующее объявление:

 func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult 

Сравнивает данные даты с указанным компонентом, сообщая им о ordered​Same если они одинаковы в данном компоненте и всех более крупных компонентах, иначе либо ordered​Ascending либо ordered​Descending .

Ниже приведенный ниже код игровой площадки показывает, как использовать его:

 import Foundation let calendar = Calendar.current let date1 = Date() // "Mar 31, 2017, 2:01 PM" let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM" let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM" /* Compare date1 and date2 */ do { let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day) switch comparisonResult { case ComparisonResult.orderedSame: print("Same day") default: print("Not the same day") } // Prints: "Not the same day" } /* Compare date1 and date3 */ do { let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day) if case ComparisonResult.orderedSame = comparisonResult { print("Same day") } else { print("Not the same day") } // Prints: "Same day" } 

# 2. Использование dateComponents(_:from:to:)

Calendar есть метод, называемый dateComponents(_:from:to:) . dateComponents(_:from:to:) имеет следующее объявление:

 func dateComponents(_ components: Set, from start: Date, to end: Date) -> DateComponents 

Возвращает разницу между двумя датами.

Ниже приведенный ниже код игровой площадки показывает, как использовать его:

 import Foundation let calendar = Calendar.current let date1 = Date() // "Mar 31, 2017, 2:01 PM" let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM" let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM" /* Compare date1 and date2 */ do { let dateComponents = calendar.dateComponents([.day], from: date1, to: date2) switch dateComponents.day { case let value? where value < 0: print("date2 is before date1") case let value? where value > 0: print("date2 is after date1") case let value? where value == 0: print("date2 equals date1") default: print("Could not compare dates") } // Prints: date2 is before date1 } /* Compare date1 and date3 */ do { let dateComponents = calendar.dateComponents([.day], from: date1, to: date3) switch dateComponents.day { case let value? where value < 0: print("date2 is before date1") case let value? where value > 0: print("date2 is after date1") case let value? where value == 0: print("date2 equals date1") default: print("Could not compare dates") } // Prints: date2 equals date1 } 

Документация относительно NSDate указывает, что методы compare: and isEqual: оба будут выполнять базовое сравнение и упорядочивать результаты, хотя они все равно будут isEqual: на время.

Вероятно, самым простым способом справиться с задачей было бы создать новый метод isToday для реализации следующего:

 - (bool)isToday:(NSDate *)otherDate { currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code if (currentTime < [otherDate timeIntervalSinceNow]) { return YES; } else { return NO; } } 

Это особенно уродливая кошка для кожи, но вот еще один способ сделать это. Я не говорю, что это изящно, но, вероятно, это так близко, как вы можете получить поддержку даты / времени в iOS.

 bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]]; 
 NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit; NSDateComponents *comp = [cal components:unit fromDate:nowDate toDate:setDate options:0]; NSString *dMonth; dMonth = [NSString stringWithFormat:@"%02ld",comp.month]; NSString *dDay; dDay = [NSString stringWithFormat:@"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)]; 

сравнить час, а также исправить разницу в 1день

  • Как обрабатывать дублируемую символьную ошибку от сторонних библиотек?
  • Остановить UIWebView от «подпрыгивания» по вертикали?
  • Потяните, чтобы обновить UITableView без UITableViewController
  • Как размыть сцену в SpriteKit?
  • CALayer: добавить границу только с одной стороны
  • UISwitch в ячейке UITableView
  • Редактирование Info.plist возможно программно?
  • Эквивалент карты NSArray
  • Ошибка модуля сборки iOS8 для Facebook для FBSDKCoreKit
  • Создание пользовательского UIKeyBoard для iPhone
  • Выполнение команды терминала из приложения Cocoa
  • Interesting Posts

    Достаточно ли перенаправлять изображения HTTP?

    Быстрее процессор или больше оперативной памяти?

    Блокнот ++ дергает

    Синхронизация клиентской базы данных SQLite с базой данных сервера MySQL

    Как работать с URISyntaxException

    Windows 7 застрял на CLASSPNP.SYS

    Где разместить и как читать файлы ресурсов конфигурации в приложении на основе сервлета?

    Как печатать в черно-белом режиме, когда цветной картридж закончился чернилами

    Как использовать STL очереди приоритетов для объектов?

    Включите другой JSP-файл

    ItemsControl с несколькими DataTemplates для viewmodel

    FileSystemWatcher против опроса для просмотра изменений файла

    Как эффективно диагностировать дросселирование интернет-провайдера (или другие проблемы, связанные с Интернетом) и что с этим делать?

    как вы можете легко проверить, запрещен ли доступ к файлу в .NET?

    Используйте Java и RegEx для преобразования оболочки в строку

    Давайте будем гением компьютера.