Comment vérifier si une NSDate
appartient à aujourd'hui?
J'avais l'habitude de le vérifier en utilisant les 10 premiers caractères de [aDate description]
. [[aDate description] substringToIndex:10]
renvoie une chaîne semblable à "YYYY-MM-DD"
. J'ai donc comparé la chaîne à la chaîne renvoyée par [[[NSDate date] description] substringToIndex:10]
.
Y at-il plus moyen rapide et/ou soigné de vérifier?
Merci.
Dans macOS 10.9+ et iOS 8+, une méthode sur NSCalendar/Calendar fait exactement cela!
- (BOOL)isDateInToday:(NSDate *)date
Donc vous feriez simplement
Objectif c:
BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];
Swift 3:
let today = Calendar.current.isDateInToday(date)
Vous pouvez comparer les composants de date:
NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
[today month] == [otherDay month] &&
[today year] == [otherDay year] &&
[today era] == [otherDay era]) {
//do stuff
}
Modifier:
J'aime plus la méthode de stefan, je pense que cela donne une déclaration plus propre et plus compréhensible si:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];
if([today isEqualToDate:otherDate]) {
//do stuff
}
Chris, j'ai intégré votre suggestion. Je devais regarder quelle époque était, alors pour ceux qui ne le savent pas, cela fait une distinction entre la Colombie-Britannique et la Colombie-Britannique. C'est probablement inutile pour la plupart des gens, mais il est facile à vérifier et ajoute une certitude, alors je l'ai inclus. Si vous visez la vitesse, ce n’est probablement pas une bonne méthode.
NOTEcomme avec beaucoup de réponses sur SO, après 7 ans, c'est totalement obsolète. Dans Swift, utilisez simplement .isDateInToday
Ceci est une ramification de votre question, mais si vous souhaitez imprimer un NSDate avec "Aujourd'hui" ou "Hier", utilisez la fonction
- (void)setDoesRelativeDateFormatting:(BOOL)b
pour NSDateFormatter
Je voudrais essayer d'obtenir la date d'aujourd'hui normalisée à minuit et la deuxième date, normaliser à minuit puis comparer si c'est le même NSDate.
De un exemple Apple voici comment vous normalisez à minuit la date du jour, faites de même pour la deuxième date et comparez:
NSCalendar * gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
[gregorian components:
(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
Travailler Extension Swift 3 & 4 de la suggestion de Catfish_Man:
extension Date {
func isToday() -> Bool {
return Calendar.current.isDateInToday(self)
}
}
Pas besoin de jongler avec des composants, des époques et des choses.
NSCalendar fournit une méthode pour obtenir le début d'une certaine unité de temps pour une date existante.
Ce code aura le début d'aujourd'hui et une autre date et comparera cela. Si la valeur est NSOrderedSame
, les deux dates ont lieu le même jour, donc aujourd'hui.
NSDate *today = nil;
NSDate *beginningOfOtherDate = nil;
NSDate *now = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&today interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfOtherDate interval:NULL forDate:beginningOfOtherDate];
if([today compare:beginningOfOtherDate] == NSOrderedSame) {
//otherDate is a date in the current day
}
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:self)
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
Travaillé pour moi sur Swift 2.0
Version rapide de la meilleure réponse:
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:aDate);
let otherDate = cal.dateFromComponents(components)!
if(today.isEqualToDate(otherDate)) {
//do stuff
}
Vous pouvez également vérifier l'intervalle de temps entre la date que vous avez et la date du jour:
[myDate timeIntervalSinceNow]
Cela vous donnera l'intervalle de temps, en secondes, entre myDate et la date/heure actuelle.
Lien .
Edit: Note pour tout le monde: Je suis bien conscient que [myDate timeIntervalSinceNow] ne détermine pas sans ambiguïté si myDate est aujourd'hui.
Je laisse cette réponse telle quelle afin que, si quelqu'un recherche quelque chose de similaire et qu'il soit utile [myDate timeIntervalSinceNow], il se peut qu'il le trouve ici.
Reportez-vous à l'entrée de documentation d'Apple intitulée "Effectuer des calculs de calendrier" [lien] .
Le Listing 13 sur cette page suggère que pour déterminer le nombre de minuit entre les jours, vous utilisez:
- (NSInteger)midnightsFromDate:(NSDate *)startDate toDate:(NSDate *)endDate
{
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSInteger startDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:startDate];
NSInteger endDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:endDate];
return endDay - startDay;
}
Vous pouvez ensuite déterminer si deux jours sont identiques en utilisant cette méthode et en vérifiant s’il renvoie 0 ou non.
Swift Extension basé sur les meilleures réponses:
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
if cal.respondsToSelector("isDateInToday:") {
return cal.isDateInToday(self)
}
var components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:self);
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
}
Il existe un moyen plus facile que la plupart des réponses ci-dessus!
NSDate *date = ... // The date you wish to test
NSCalendar *calendar = [NSCalendar currentCalendar];
if([calendar isDateInToday:date]) {
//do stuff
}
Si vous avez beaucoup de comparaisons de dates, les appels à calendar:components:fromDate
commencent à prendre beaucoup de temps. Selon certains profils que j'ai faits, ils semblent être assez coûteux.
Supposons que vous tentiez de déterminer quelles dates, par exemple NSArray *datesToCompare
, sont identiques à un jour donné, par exemple NSDate *baseDate
, vous pouvez utiliser un des paramètres suivants (partiellement adapté d'une réponse ci-dessus):
NSDate *baseDate = [NSDate date];
NSArray *datesToCompare = [NSArray arrayWithObjects:[NSDate date],
[NSDate dateWithTimeIntervalSinceNow:100],
[NSDate dateWithTimeIntervalSinceNow:1000],
[NSDate dateWithTimeIntervalSinceNow:-10000],
[NSDate dateWithTimeIntervalSinceNow:100000],
[NSDate dateWithTimeIntervalSinceNow:1000000],
[NSDate dateWithTimeIntervalSinceNow:50],
nil];
// determine the NSDate for midnight of the base date:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:baseDate];
NSDate* theMidnightHour = [calendar dateFromComponents:comps];
// set up a localized date formatter so we can see the answers are right!
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
// determine which dates in an array are on the same day as the base date:
for (NSDate *date in datesToCompare) {
NSTimeInterval interval = [date timeIntervalSinceDate:theMidnightHour];
if (interval >= 0 && interval < 60*60*24) {
NSLog(@"%@ is on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
else {
NSLog(@"%@ is NOT on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
}
Sortie:
Nov 23, 2011 1:32:00 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:33:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:48:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 10:45:20 AM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 24, 2011 5:18:40 PM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Dec 5, 2011 3:18:40 AM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:32:50 PM is on the same day as Nov 23, 2011 1:32:00 PM
pour iOS7 et les versions antérieures:
//this is now => need that for the current date
NSDate * now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents * components = [calendar components:( NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: now];
[components setMinute:0];
[components setHour:0];
[components setSecond:0];
//this is Today's Midnight
NSDate *todaysMidnight = [calendar dateFromComponents: components];
//now timeIntervals since Midnight => in seconds
NSTimeInterval todayTimeInterval = [now timeIntervalSinceDate: todaysMidnight];
//now timeIntervals since OtherDate => in seconds
NSTimeInterval otherDateTimeInterval = [now timeIntervalSinceDate: otherDate];
if(otherDateTimeInterval > todayTimeInterval) //otherDate is not in today
{
if((otherDateTimeInterval - todayTimeInterval) <= 86400) //86400 == a day total seconds
{
@"yesterday";
}
else
{
@"earlier";
}
}
else
{
@"today";
}
now = nil;
calendar = nil;
components = nil;
todaysMidnight = nil;
NSLog("Thank you :-)");
Cela pourrait probablement être retravaillé en tant que catégorie NSDate, mais j’ai utilisé:
// Seconds per day (24h * 60m * 60s)
#define kSecondsPerDay 86400.0f
+ (BOOL) dateIsToday:(NSDate*)dateToCheck
{
// Split today into components
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comps = [gregorian components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit)
fromDate:[NSDate date]];
// Set to this morning 00:00:00
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
NSDate* theMidnightHour = [gregorian dateFromComponents:comps];
[gregorian release];
// Get time difference (in seconds) between date and then
NSTimeInterval diff = [dateToCheck timeIntervalSinceDate:theMidnightHour];
return ( diff>=0.0f && diff<kSecondsPerDay );
}
(Cependant, comparer les deux chaînes de date comme dans la question initiale semble presque "plus propre" ..)
Consultez notre superbe NSDate extension
d'Erica Sadun. Très simple à utiliser. C'est bon ici:
http://github.com/erica/NSDate-Extensions
C'est déjà là dans cet article: https://stackoverflow.com/a/4052798/362310
La solution correcte et sûre sans décompression forcée, fonctionnant sur Swift 2.2 et avant iOS 8:
func isToday() -> Bool {
let calendar = NSCalendar.currentCalendar()
if #available(iOS 8.0, *) {
return calendar.isDateInToday(self)
}
let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let dayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:self)
guard let today = calendar.dateFromComponents(todayComponents),
day = calendar.dateFromComponents(dayComponents) else {
return false
}
return today.compare(day) == .OrderedSame
}