Question

Quelle est la manière la plus efficace / recommandé de comparer deux NSDates? Je voudrais être en mesure de voir si les deux dates sont le même jour, quel que soit le temps et ont commencé à écrire un code qui utilise le timeIntervalSinceDate: méthode dans la classe NSDate et obtient l'entier de cette valeur divisée par le nombre de secondes en un jour. Cela semble longue haleine et je me sens comme je manque quelque chose évidente.

Le code que je suis en train de fixer est:

if (!([key compare:todaysDate] == NSOrderedDescending))
{
    todaysDateSection = [eventSectionsArray count] - 1;
}

où clés et DateDuDour sont des objets NSDate et DateDuDour crée en utilisant:

NSDate *todaysDate = [[NSDate alloc] init];

Cordialement

Dave

Était-ce utile?

La solution

Vous définissez l'heure à la date 00:00:00 avant de faire la comparaison:

unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar* calendar = [NSCalendar currentCalendar];

NSDateComponents* components = [calendar components:flags fromDate:date];

NSDate* dateOnly = [calendar dateFromComponents:components];

// ... necessary cleanup

Ensuite, vous pouvez comparer les valeurs de date. Voir la liste de .

Autres conseils

Je suis surpris qu'il n'y a pas d'autres réponses ont cette option pour obtenir la date « début de la journée » pour les objets:

[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];

Ce qui définit date1 et date2 au début de leurs jours respectifs. Si elles sont égales, ils sont le même jour.

Ou cette option:

NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];

Ce qui définit day1 et day2 à des valeurs quelque peu arbitraires qui peuvent être comparés. Si elles sont égales, ils sont le même jour.

Il y a une nouvelle méthode qui a été présenté à NSCalendar avec iOS 8 qui rend ce beaucoup plus facile.

- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);

Vous définissez la granularité à l'unité (s) que la matière. Ce ne tient pas compte toutes les autres unités et limite par rapport à celles sélectionnées.

je l'approche Duncan C, j'ai corrigé quelques erreurs qu'il a commises

-(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate { 

    NSCalendar *currentCalendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0];

    NSInteger days = [components day];

    return days;
}

J'utilise cette méthode peu util:

-(NSDate*)normalizedDateWithDate:(NSDate*)date
{
   NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
                                              fromDate: date];
   return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized
}

(Vous devez évidemment avoir un Ivar appelé calendar_ contenant un NSCalendar.)

Avec cela, il est facile de vérifier si une date est aujourd'hui comme ceci:

[[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]];

([NSDate date] retourne la date et l'heure.)

Ceci est bien sûr très semblable à ce que suggère Gregory. L'inconvénient de cette approche est qu'elle a tendance à créer beaucoup d'objets temporaires NSDate. Si vous allez traiter beaucoup de dates, je vous conseille d'utiliser une autre méthode, comme la comparaison des composants directement, ou de travailler avec des objets NSDateComponents au lieu de NSDates.

La réponse est plus simple que tout le monde en fait être. NSCalendar a une méthode

components:fromDate:toDate:options

Cette méthode vous permet de calculer la différence entre deux dates en utilisant toutes les unités que vous voulez.

Alors écrire une méthode comme ceci:

-(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate)
{
  NSCalendar *currentCalendar = [NSCalendar currentCalendar];
  NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit
    fromDate: firstDate 
    toDate: secondDate
    options: 0];

  NSInteger days = [components days];
  return days;
}

Si la méthode ci-dessus renvoie zéro, les deux dates sont le même jour.

Pour les développeurs de codage à Swift 3

if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
     // Do something
}

Avec Swift 3, selon vos besoins, vous pouvez choisir l'un des deux modèles suivants afin de résoudre votre problème.


# 1. En utilisant la méthode de compare(_:to:toGranularity:)

Calendar a une méthode appelée compare(_:​to:​to​Granularity:​) . compare(_:​to:​to​Granularity:​) a la déclaration suivante:

func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
  

Compares les dates indiquées jusqu'à la composante donnée, les rapports ordered​Same si elles sont les mêmes dans le composant donné et tous les composants plus grands, sinon soit ordered​Ascending ou ordered​Descending.

Le code ci-dessous montre Playground chaud pour l'utiliser:

import Foundation

let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"

/* Compare date1 and date2 */
do {
    let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day)
    switch comparisonResult {
    case ComparisonResult.orderedSame:
        print("Same day")
    default:
        print("Not the same day")
    }
    // Prints: "Not the same day"
}

/* Compare date1 and date3 */
do {
    let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day)
    if case ComparisonResult.orderedSame = comparisonResult {
        print("Same day")
    } else {
        print("Not the same day")
    }
    // Prints: "Same day"
}

# 2. En utilisant dateComponents(_:from:to:)

Calendar a une méthode appelée dateComponents(_:from:to:) . dateComponents(_:from:to:) a la déclaration suivante:

func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents
  

Renvoie la différence entre deux dates.

Le code ci-dessous montre Playground chaud pour l'utiliser:

import Foundation

let calendar = Calendar.current
let date1 = Date() // "Mar 31, 2017, 2:01 PM"
let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"

/* Compare date1 and date2 */
do {
    let dateComponents = calendar.dateComponents([.day], from: date1, to: date2)
    switch dateComponents.day {
    case let value? where value < 0:
        print("date2 is before date1")
    case let value? where value > 0:
        print("date2 is after date1")
    case let value? where value == 0:
        print("date2 equals date1")
    default:
        print("Could not compare dates")
    }
    // Prints: date2 is before date1
}

/* Compare date1 and date3 */
do {
    let dateComponents = calendar.dateComponents([.day], from: date1, to: date3)
    switch dateComponents.day {
    case let value? where value < 0:
        print("date2 is before date1")
    case let value? where value > 0:
        print("date2 is after date1")
    case let value? where value == 0:
        print("date2 equals date1")
    default:
        print("Could not compare dates")
    }
    // Prints: date2 equals date1
}
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}

ma solution était deux conversions avec NSDateFormatter:

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyyMMdd"];
    [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

    NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0];
    NSString *todayString=[dateFormat stringFromDate:today];
    NSDate *todayWithoutHour=[dateFormat dateFromString:todayString];

    if ([today compare:exprDate] == NSOrderedDescending)
    {
       //do  
    }

La documentation relative NSDate indique que les méthodes de compare: et isEqual: seront à la fois effectuer une comparaison de base et commander les résultats, mais ils facteur encore dans le temps.

Probablement la façon la plus simple de gérer la tâche serait de créer une nouvelle méthode de isToday à l'effet des éléments suivants:

- (bool)isToday:(NSDate *)otherDate
{
    currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code

    if (currentTime < [otherDate timeIntervalSinceNow])
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

Ceci est un chat particulièrement laid à la peau, mais voici une autre façon de le faire. Je ne dis pas que c'est élégant, mais il est probablement aussi proche que vous pouvez obtenir avec le soutien de date / heure dans iOS.

bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit;
NSDateComponents *comp = [cal components:unit
                                fromDate:nowDate
                                  toDate:setDate
                                 options:0];

NSString *dMonth;
dMonth = [NSString stringWithFormat:@"%02ld",comp.month];
NSString *dDay;
dDay = [NSString stringWithFormat:@"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)];

comparer heure et de fixer la différence 1 jour

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top