Мне нужно знать, есть ли два экземпляра NSDate с одного дня.
Есть ли более простой/лучший способ сделать это, чем получить NSDateComponents и сравнить день/месяц/год?
Мне нужно знать, есть ли два экземпляра NSDate с одного дня.
Есть ли более простой/лучший способ сделать это, чем получить NSDateComponents и сравнить день/месяц/год?
NSDateComponents звучит как лучший выбор для меня. Другая тактика, которую нужно попробовать, - это бесплатный доступ к CFDate, затем использование CFDateGetAbsoluteTime и выполнение вычитания, чтобы получить промежуток времени между двумя датами. Однако вам нужно будет сделать дополнительную математику, чтобы выяснить, имеет ли разница во времени даты в тот же день.
Если вы настроите таргетинг на iOS 8 (и OS X 10.9) или более позднюю версию, то Ответ на Joe - лучшее решение, использующее новый метод в 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];
}
Если вы работаете с 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.
(Примечание: посмотрите на ответ Джо на хороший способ сделать это на iOS 8 +)
Я просто использую формат даты:
NSDateFormatter *dateComparisonFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"];
if( [[dateComparisonFormatter stringFromDate:firstDate] isEqualToString:[dateComparisonFormatter stringFromDate:secondDate]] ) {
…
}
НТН.
В Swift:
NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)
Он вернет true, если они находятся в тот же день.
Мне нравится решение progrmr, но я бы пошел еще дальше и создаю категорию NSDate
, которая предоставляет этот метод. Это сделает ваш код немного более читабельным, и вам не нужно будет копировать и вставлять этот метод в каждый новый класс, который может ему понадобиться, - просто импортируйте файл заголовка.
@interface NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate;
@end
#import "NSDate+SameDay.h"
@implementation NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate {
// From progrmr 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...
}
Я использую 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];
}
NSCalendar.currentCalendar().isDateInToday(yourNSDate)
Доступно в iOS 8.0 и более поздних версиях и OS X версии 10.9 и более поздних версий.
Есть ли более простой/лучший способ сделать это, чем получить 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;
в Swift 3.0, iOS8 +
if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) {
}
или
if NSCalendar.current.isDateInToday(date) {
}
Я создаю свои собственные классы полезности.
@interface ZYUtility : NSObject
+ (NSDate *)yesterday;
+ (NSDate *)tomorrow;
+ (NSDate *)endOfDay:(NSDate *)date;
+ (NSDate *)beginningOfDay:(NSDate *)date;
@end
+ (NSDate *)yesterday;
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:[NSDate date]];
componets.day -= 1;
componets.hour = 24;
componets.minute = 0;
componets.second = 0;
return [calendar dateFromComponents:componets];
}
+ (NSDate *)tomorrow;
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:[NSDate date]];
componets.day += 1;
componets.hour = 0;
componets.minute = 0;
componets.second = 0;
return [calendar dateFromComponents:componets];
}
+ (NSDate *)beginningOfDay:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comp = [calendar components:unitFlags fromDate:date];
return [calendar dateFromComponents:comp];
}
+ (NSDate *)endOfDay:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.day = 1;
NSDate *theDate = [calendar dateByAddingComponents:components
toDate:[ZYUtility beginningOfDay:date]
options:0];
theDate = [theDate dateByAddingTimeInterval:-1];
return theDate;
}
Следующее проверит, соответствуют ли две даты в тот же день в заданную эпоху (что достаточно во многих случаях):
- (BOOL)isDate:(NSDate *)date1 sameDayAsDate:(NSDate *)date2 {
NSCalendar *calendar = [NSCalendar currentCalendar];
int diff = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:date1] -
[calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:date2];
return 0 == diff;
}