J'ai besoin de savoir si deux instances NSDate proviennent toutes deux du même jour.
Existe-t-il un moyen plus facile/meilleur de le faire que d'obtenir les NSDateComponents et de comparer le jour/mois/année?
NSDateComponents sonne comme le meilleur pari pour moi. Une autre tactique à essayer consiste à le connecter sans frais à un CFDate, puis à utiliser CFDateGetAbsoluteTime et à effectuer une soustraction pour obtenir le temps entre les deux dates. Vous devrez cependant faire quelques calculs supplémentaires pour déterminer si le décalage horaire arrive les dates le même jour.
Si vous ciblez iOS 8 (et OS X 10.9) ou une version ultérieure , alors réponse de Joe est une meilleure solution en utilisant une nouvelle dans NSCalendar juste à cet effet:
-[NSCalendar isDate:inSameDayAsDate:]
Pour iOS 7 ou version antérieure : NSDateComponents est ma préférence. Que diriez-vous quelque chose comme ça:
- (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];
}
Si vous travaillez avec iOS 8, vous pouvez utiliser -isDate:inSameDayAsDate:
.
De 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);
Notez que pour une raison quelconque, cela n'a pas été présenté dans la documentation officielle sur le site des développeurs d'Apple. Mais cela fait définitivement partie de l'API publique.
(Remarque: regardez la réponse de Joe pour un bon moyen de le faire sur iOS 8+)
J'utilise juste un formateur de date:
NSDateFormatter *dateComparisonFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"];
if( [[dateComparisonFormatter stringFromDate:firstDate] isEqualToString:[dateComparisonFormatter stringFromDate:secondDate]] ) {
…
}
HTH.
Dans Swift:
NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)
Cela reviendra vrai s'ils sont le même jour.
J'aime la solution de progrmr, mais j'irais encore plus loin et ferais une catégorie de NSDate
qui fournit cette méthode. Cela rendra votre code légèrement plus lisible, et vous n'aurez pas besoin de copier et coller la méthode dans chaque nouvelle classe qui pourrait en avoir besoin - il suffit d'importer le fichier d'en-tête.
@interface NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate;
@end
#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
Ensuite, après avoir importé NSDate+SameDay.h
dans votre classe, vous pouvez l'utiliser comme ceci:
if ([myFirstDate isSameDayAsDate:mySecondDate]) {
// The two dates are on the same day...
}
J'utilise NSDateComponents pour éliminer l'aspect temps, puis comparer. Quelque chose comme:
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)
Disponible dans iOS 8.0 et versions ultérieures et OS X v10.9 et versions ultérieures.
dans Swift 3.0, iOS8 +
if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) {
}
ou
if NSCalendar.current.isDateInToday(date) {
}
Existe-t-il un moyen plus facile/meilleur de le faire que d'obtenir les NSDateComponents et de comparer le jour/mois/année?
Oui, il existe un moyen plus simple
-[NSCalendar rangeForUnit:startDate:interval:forDate:]
Cette méthode permet de définir facilement une date au début d'une unité (jour, heure, mois, année,…) et d'obtenir la longueur (intervalle) de cette unité.
En tant que catégorie, il pourrait être utilisé comme
@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
Cette catégorie devrait fonctionner pour toutes les versions iOS et Mac OS X 10.5+.
pour iOS 8+ et Mac OS X 10.9+, vous pouvez utiliser NSCalendars
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;