Какао-Touch: Как я могу увидеть, если два NSDates в один день? - PullRequest
67 голосов
/ 13 октября 2009

Мне нужно знать, оба ли экземпляра NSDate относятся к одному и тому же дню.

Есть ли более простой / лучший способ сделать это, чем получить NSDateComponents и сравнить день / месяц / год?

Ответы [ 12 ]

154 голосов
/ 14 октября 2009

Если вы нацелены на iOS 8 (и OS X 10.9) или новее , тогда Ответ Джо - лучшее решение, использующее новый метод в NSCalendar как раз для этой цели:

-[NSCalendar isDate:inSameDayAsDate:]

Для iOS 7 или более ранней версии : NSDateComponents - это мои предпочтения. Как насчет такого:

- (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];
}
53 голосов
/ 31 января 2015

Если вы работаете с 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);

Обратите внимание, что по какой-то причине это не вошло в официальную документацию на сайте разработчиков Apple. Но это определенно часть публичного API.

24 голосов
/ 13 октября 2009

(Примечание: посмотрите на ответ Джо, чтобы найти хороший способ сделать это на iOS 8 +)

Я просто использую форматировщик даты:

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

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

НТН.

13 голосов
/ 27 января 2016

В Свифт:

NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)

Возвращается значение true, если они находятся в один и тот же день.

11 голосов
/ 06 февраля 2014

Мне нравится решение progrmr, но я бы пошел еще дальше и сделал бы категорию NSDate, которая предоставляет этот метод. Это сделает ваш код немного более читабельным, и вам не нужно будет копировать и вставлять метод в каждый новый класс, который может понадобиться - просто импортируйте файл заголовка.

NSDate + SameDay.h

@interface NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate;
@end

NSDate + SameDay.m

#import "NSDate+SameDay.h"

@implementation NSDate (SameDay)

- (BOOL)isSameDayAsDate:(NSDate*)otherDate {

    // From progrmr's answer...
    NSCalendar* calendar = [NSCalendar currentCalendar];

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

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

@end

Затем, после импорта NSDate+SameDay.h в ваш класс, вы можете использовать его так:

if ([myFirstDate isSameDayAsDate:mySecondDate]) {
    // The two dates are on the same day...
}
7 голосов
/ 13 октября 2009

NSDateComponents звучит как лучшая ставка для меня. Еще одна тактика, которую можно попробовать - это бесплатное соединение CFDate с последующим использованием CFDateGetAbsoluteTime и вычитанием, чтобы получить промежуток времени между двумя датами. Однако вам придется выполнить некоторые дополнительные математические расчеты, чтобы выяснить, соответствует ли разница во времени датам того же дня.

5 голосов
/ 14 октября 2009

Я использую 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];
}
4 голосов
/ 19 июня 2016
NSCalendar.currentCalendar().isDateInToday(yourNSDate)

Доступно в iOS 8.0 и более поздних версиях и OS X v10.9 и более поздних версиях.

1 голос
/ 17 марта 2017

в Swift 3.0, iOS8 +

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

}

или

if NSCalendar.current.isDateInToday(date) {

}
1 голос
/ 08 марта 2015

Есть ли более простой / лучший способ сделать это, чем получить NSDateComponents и сравнить день / месяц / год?

Да, есть более простой способ

-[NSCalendar rangeForUnit:startDate:interval:forDate:] Этот метод позволяет легко установить дату начала единицы (день, час, месяц, год, ...) и получить длину (интервал) этой единицы.

В качестве категории может использоваться как

@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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...