比较两个NSDates并忽略时间组件

什么是比较两个NSDates最有效/推荐的方法? 我希望能够看到两个date是否在同一天,而不考虑时间,并开始编写一些使用NSDate类中的timeIntervalSinceDate:方法的代码,并获取该值的整数除以秒数一天内。 这似乎很长时间了,我觉得我失去了一些明显的东西。

我试图解决的代码是:

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

其中key和todaysDate是NSDate对象,而todaysDate是使用以下命令创build的:

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

问候

戴夫

在进行比较之前,您将date的时间设置为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 

然后你可以比较date值。 请参阅参考文档中的概述 。

我很惊讶没有其他的答案有这个选项来获取对象的“开始date”date:

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

其中将date1date2设置为各自的天数的开始。 如果他们是平等的,他们在同一天。

或者这个选项:

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

其中将day1day2为可以比较的有些随意的值。 如果他们是平等的,他们在同一天。

有一个新的方法,引入NSCalendar与iOS 8,使这更容易。

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

您将粒度设置为重要的单位。 这忽视了所有其他单位,并限制与所select的单位进行比较。

对于iOS8和更高版本,检查两个date是否在同一天发生就像下面这样简单:

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

见文件

这是所有答案的简写:

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

我用邓肯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; } 

我使用这个小的util方法:

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

(你显然需要一个名为calendar_的伊娃包含一个NSCalendar 。)

使用这个,很容易检查date是否是这样的:

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

[NSDate date]返回当前date和时间。)

这当然和Gregory所说的非常相似。 这种方法的缺点是它倾向于创build大量的临时NSDate对象。 如果您要处理大量的date,我会推荐使用其他方法,例如直接比较组件,或使用NSDateComponents对象而不是NSDates

答案比每个人都明白的要简单。 NSCalendar有一个方法

 components:fromDate:toDate:options 

该方法可以让你用任何你想要的单位来计算两个date之间的差异。

所以写一个像这样的方法:

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

如果上述方法返回零,这两个date是在同一天。

从iOS 8.0开始,您可以使用:

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

如果结果是例如NSOrderedDescending,otherDate在[NSDatedate]之前以天计。

我没有在NSCalendar文档中看到这个方法,但是它在iOS 7.1到iOS 8.0 API差异中

 int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24); if (interval!=0){ //not the same day; } 

我的解决scheme是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编码的开发人员

 if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){ // Do something } 

有关NSDate的文档指出, compare:isEqual:方法将执行基本比较并对结果进行sorting,尽pipe它们仍然是时间因素。

pipe理这个任务的最简单方法可能是创build一个新的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中的date/时间支持相近。

 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天的差异

随着Swift 3,根据您的需求,您可以select以下两种模式之一,以解决您的问题。


#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 

将给定date与给定组件进行比较,如果它们在给定组件和所有较大组件中ordered​Same ,则报告它们ordered​Same ,否则ordered​Ascendingordered​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<Calendar.Component>, from start: Date, to end: Date) -> DateComponents 

返回两个date之间的差异。

下面的游乐场代码显示使用它的热点:

 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 }