2010-12-01 10 views
8

J'écris une application qui utilise des données de base pour stocker mes données. Inclus dans ceci est un champ de date dont je suis seulement intéressé par la date pas l'heure. je dois sélectionner les enregistrements en fonction de la date (pas le temps) et j'ai donc créé une catégorie sur NSDate pour retourner une date, normalisée à un temps de jeu comme suit:NSDate bonne pratique dans la création d'une date sans élément de temps

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime]; 
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps]; 
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

Je puis utilisez ceci quand j'ajoute des données au core-data store (j'ai un setter qui utilise cette méthode pour définir la valeur de la date primitive) puis j'utilise cette méthode pour créer une date que j'utilise pour comparer les dates lors d'une requête d'extraction . Donc, en théorie, cela devrait toujours fonctionner - c.-à-choisir les dates que je cherche. Je suis un peu nerveux mais je ne suis pas tout à fait sûr de l'effet que cela aura sur le changement de fuseau horaire ou de paramètres régionaux. Cela fonctionnera-t-il encore?

Ce qui est considéré comme la meilleure pratique lorsque vous stockez et recherchez une date uniquement lorsque vous n'êtes pas intéressé par l'heure.

Cheers.

EDIT

Après avoir lu la discussion, je pense recommandé que je modifier mon code pour la suivante. L'idée étant que si je m'assure que je le pousse vers un système de calendrier spécifique et un fuseau horaire spécifique (UTC) alors les dates devraient toujours être les mêmes, peu importe où vous êtes lorsque vous définissez la date et quand vous lisez la date. Tous les commentaires sur ce nouveau code apprécié.

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 

NSCalendar  *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; 
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease]; 
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit 
         fromDate:dateTime]; 

NSDate *dateOnly = [calendar dateFromComponents:components]; 

[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

+0

Merci pour la solution !! : D Juste une petite correction: La ligne: '[DATEONLY dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' devrait être: 'DATEONLY = [DATEONLY dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' –

Répondre

5

Vous avez quelques questions à traiter ici. D'abord, comme vous l'avez noté, les fuseaux horaires. Vous devez également vous soucier de l'heure d'été, qui change le concept de «midi».

Jetez un oeil à this discussion sur CocoaDev où un ingénieur d'Apple donne quelques réponses et discute des meilleures pratiques.

+0

Merci pour cela. Après avoir lu cette discussion, il semble que je devrais m'assurer que j'utilise toujours le même système de calendrier et le même fuseau horaire pour stocker et comparer. J'ai ajouté un nouveau code à ma question en fonction de cette nouvelle façon de penser. – SimonB

3

Une solution plus simple consiste à utiliser un prédicat qui recherche des dates dans une certaine plage.

Utilisez NSCalendarComponent pour créer une date de début et une date de fin pour votre "jour", puis incluez celles du prédicat.

NSPredicate *p=[NSPredicate predicateWithFormat:@"[email protected] <= date <= [email protected]",startDate,endDate]; 

Cela fournira la flexibilité maximale sans trop de complexité. La programmation de la date et de l'heure est complexe. Soyez prêt à faire un peu de travail.

2

Je me suis également retrouvé dans un scénario où j'avais besoin d'un NSDate pour comparer une date sans tenir compte du temps.J'ai un mécanisme de filtre et dans le cadre de l'interface utilisateur, si l'utilisateur a choisi aujourd'hui la date minimale comme date de début et la date de fin comme aujourd'hui, je voudrais afficher "Toutes les périodes" par opposition à une chaîne dans le format :

1/5/2006 - 24/12/2009

donc je devais prendre la date d'aujourd'hui en utilisant +date de NSDate, et le comparer à la date de fin. Cette date de fin provient d'un UIDatePicker défini sur sans délai, mais +date a renvoyé la date et l'heure de ce moment.

J'ai donc écrit cette courte méthode pratique, il reçoit un objet date, utilise NSDateComponents et la classe NSCalendar pour extraire le jour, le mois et l'année.

Ces 3 paramètres sont ensuite utilisés pour créer une nouvelle NSDate en utilisant NSDateFormatter's - méthode dateFromString:, le résultat est un NSDate correspondant à la même « date » (dans le concept humain traditionnel) comme paramètre date mais sans temps.

- (NSDate *)strictDateFromDate:(NSDate *)date{ 
    NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *components = [[NSCalendar currentCalendar] components:flags 
                    fromDate:[NSDate date]]; 
    NSString *stringDate = [NSString stringWithFormat:@"%d/%d/%d", components.day, components.month, components.year]; 

    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; 
    formatter.dateFormat = @"dd/MM/yyyy"; 

    return [formatter dateFromString:stringDate]; 
} 

J'espère que vous pourrez utiliser et profiter de cette fonction à l'avenir.

+0

J'ai essayé celui-là mais les valeurs de retour contiennent aussi l'horodatage !!! –