Ios Cocoa Touch:如何判断两个日期是否在同一天?

Ios Cocoa Touch:如何判断两个日期是否在同一天?,ios,objective-c,macos,cocoa-touch,Ios,Objective C,Macos,Cocoa Touch,我需要知道两个NSDate实例是否都来自同一天 NSCalendar.currentCalendar().isDateInToday(yourNSDate) 有没有比获取NSDateComponents并比较日/月/年更简单/更好的方法呢?NSDateComponents对我来说似乎是最好的选择。另一种尝试的策略是免费将其连接到CFDate,然后使用CFDateGetAbsoluteTime并进行减法运算以获得两个日期之间的时间量。但是,您必须做一些额外的数学运算,以确定时差是否在同一天到达日

我需要知道两个NSDate实例是否都来自同一天

NSCalendar.currentCalendar().isDateInToday(yourNSDate)

有没有比获取NSDateComponents并比较日/月/年更简单/更好的方法呢?

NSDateComponents对我来说似乎是最好的选择。另一种尝试的策略是免费将其连接到CFDate,然后使用CFDateGetAbsoluteTime并进行减法运算以获得两个日期之间的时间量。但是,您必须做一些额外的数学运算,以确定时差是否在同一天到达日期。

(注意:在iOS 8+上查看Joe的答案,以获得一个很好的方法)

我只使用日期格式化程序:

NSDateFormatter *dateComparisonFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"];

if( [[dateComparisonFormatter stringFromDate:firstDate] isEqualToString:[dateComparisonFormatter stringFromDate:secondDate]] ) {
    …
}

HTH.

我使用NSDateComponents去掉时间方面,然后进行比较。比如:

if ([[self beginningOfDay:date1] isEqualToDate:[self beginningOfDay:date2]]) 
{
...
}

- (NSDate *)beginningOfDay:(NSDate *)date {
    NSCalendar *calendar = [NSCalendar currentCalendar];

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
    NSDateComponents *comp = [calendar components:unitFlags fromDate:date];

    return [calendar dateFromComponents:comp];
}

如果您的目标是iOS 8(和OS X 10.9)或更高版本,那么在NSCalendar中使用新方法是一个更好的解决方案,仅用于此目的:

-[NSCalendar isDate:inSameDayAsDate:]
对于iOS 7或更早版本:我首选NSDATE组件。像这样的怎么样:

- (BOOL)isSameDayWithDate1:(NSDate*)date1 date2:(NSDate*)date2 {
    NSCalendar* calendar = [NSCalendar currentCalendar];

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
    NSDateComponents* comp1 = [calendar components:unitFlags fromDate:date1];
    NSDateComponents* comp2 = [calendar components:unitFlags fromDate:date2];

    return [comp1 day]   == [comp2 day] &&
           [comp1 month] == [comp2 month] &&
           [comp1 year]  == [comp2 year];
}

我喜欢progrmr的解决方案,但我会更进一步,创建一个提供此方法的
NSDate
类别。它将使您的代码更具可读性,并且您不需要将该方法复制并粘贴到每个可能需要它的新类中——只需导入头文件即可

NSDate+SameDay.h NSDate+SameDay.m
然后,在类中导入
NSDate+SameDay.h
后,您可以像这样使用它:

if ([myFirstDate isSameDayAsDate:mySecondDate]) {
    // The two dates are on the same day...
}

我创建自己的实用程序类

zyputility.h zyputility.m
以下内容将测试两个日期是否代表给定纪元中的同一天(在许多情况下这已经足够):


如果您使用的是iOS 8,则可以使用
-isDate:inSameDayAsDate:

NSCalendar.h

/*
    This API compares the Days of the given dates, reporting them equal if they are in the same Day.
*/
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 NS_AVAILABLE(10_9, 8_0);
请注意,由于某些原因,这并没有出现在苹果开发者网站的官方文档中。但它肯定是公共API的一部分

有没有比获取NSDATE组件并比较日/月/年更简单/更好的方法

是的,有一个更简单的方法

-[NSCalendar rangeForUnit:startDate:interval:forDate:][/code>此方法可以轻松地将日期设置为单位的开始日期(天、小时、月、年等),并获取该单位的长度(间隔)

作为一个类别,它可以像

@interface NSDate (Comparison)
-(BOOL) isSameDay:(NSDate *)rhs;
@end

@implementation NSDate (Comparison)

-(BOOL)isSameDay:(NSDate *)rhs
{
    NSDate *lhs = self;
    NSDate *lhsStart;
    NSDate *rhsStart;

    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal rangeOfUnit:NSCalendarUnitDay startDate:&lhsStart interval:NULL forDate:lhs];
    [cal rangeOfUnit:NSCalendarUnitDay startDate:&rhsStart interval:NULL forDate:rhs];
    return [lhsStart compare:rhsStart] == NSOrderedSame;
}

@end
此类别适用于所有iOS版本和Mac OS X 10.5+

对于iOS 8+和Mac OS X 10.9+,您可以使用NSCalendars

- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;
迅速:

NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)
如果它们在同一天,则返回true

NSCalendar.currentCalendar().isDateInToday(yourNSDate)
在iOS 8.0及更高版本和OS X v10.9及更高版本中提供。

在Swift 3.0、iOS 8中+

if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) {

}


这比使用NSDateComponents更糟糕,因为格式化程序必须首先将日期分解为组件,然后创建两个字符串,然后比较字符串。您的“更好”指标是什么?我认为这比类似的NSDateComponents代码“更简单”,因为它更简洁,易于维护。我一直在使用dateComponents方法,但这要聪明得多。代码越短越好,如果性能有问题,我可以缓存NSDateFormatter。对我来说很好,很聪明。为我节省了所有的NSCalendar开销。是的,但是在处理时间方面,你不得不考虑很多事情,以至于你最终编写的代码比仅仅使用NSDateComponents要多。对;我曾建议使用NSDATE组件的替代方案,但仍然认为这是最好的选择。如果这成为代码的性能关键部分,则替代方案可能会稍微快一点,但在证明有必要之前,我会避免这种优化。
NSDate
有一个很好的方法:
timeintervalncedate:
因此您甚至不需要corefoundation.NSDateComponents是最好的选择,因为这样时区和夏令时之类的事情都会自动处理。光是时间间隔还不足以确定是否有两个日期是同一天。晚上11点59分和上午12点01分只是两分钟的间隔,但不同的日子不同。您可以使用时间间隔快速排除大于24小时的间隔,然后使用NSDATE组件进行完整检查。这对每个日期使用两个转换(组件:fromDate和dateFromComponents)。我只使用组件:fromDate,从每个组件中提取月/日/年,并比较这3个整数,看它们是否匹配。您不应该使用开始日期,不是所有日期都从上午12点开始。您应该使用中午(中午12点)进行不在乎时间日期的比较签名应该是:-(BOOL)isSameDayWithDate1:(NSDate*)date2:(NSDate*)date2{(BOOL)date:(NSDate*)date1是sameDayAsDate:(NSDate*)date2读起来更好:)或者另一种方式:
-(BOOL)isDate:(NSDate*)date1 sameDayAsDate:(NSDate*)date2
返回[comp1相等:comp2];似乎给出了相同的结果。有什么区别吗?为什么选择手动比较日、月和年?@Alex:isEqual函数没有记录在NSDateComponents类引用中,因此不确定它在所有情况下都会做正确的事情。它会忽略无效的组件吗?可能,但不是docum这段代码只稍微长一点,即使单位包含其他字段(如小时或分钟),也能给出正确的结果调用组件时:fromDate:我也认为这是更好的方法。可从iOS 8.0获得。您可能希望对此重新评估已接受的答案。情况已发生变化。还有
Calendar.current.isDate(date1:Date,inSameDayAs date2:Date)
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;
NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)
NSCalendar.currentCalendar().isDateInToday(yourNSDate)
if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) {

}
if NSCalendar.current.isDateInToday(date) {

}