2009-08-25 7 views
5

Je crée un générateur de rapport dans Cocoa, et j'ai besoin de produire des plages de dates convenables telles que "Aujourd'hui", "Cette semaine", "Ce mois", "Cette année", etcComment puis-je générer des plages de dates appropriées en fonction d'un NSDate donné?

Y at-il un bon moyen de le faire? Voici mon squelette jusqu'ici:

@interface DateRange : NSObject 
{ 
    NSDate startDate; 
    NSDate endDate; 
} 

@property (nonatomic, retain) NSDate * startDate; 
@property (nonatomic, retain) NSDate * endDate; 

+ (DateRange *)rangeForDayContainingDate:(NSDate *)date; 
+ (DateRange *)rangeForWeekContainingDate:(NSDate *)date; 
+ (DateRange *)rangeForMonthContainingDate:(NSDate *)date; 
+ (DateRange *)rangeForYearContainingDate:(NSDate *)date; 

@end 

Quelques exemples de cas d'utilisation seraient les suivantes:

DateRange * thisWeek = [DateRange rangeForWeekContainingDate:[NSDate date]]; 
DateRange * thisYear = [DateRange rangeForYearContainingDate:[NSDate date]]; 

Essentiellement, je veux que le retour objet DateRange pour contenir les dates de début et de fin de la semaine, mois ou année entourant la date cible. Par exemple (en pseudocode):

NSDate * today = [August 25, 2009]; 
DateRange * thisWeek = [DateRange rangeForWeekContainingDate:today]; 
assert(thisWeek.startDate == [August 23, 3009]); 
assert(thisWeek.endDate == [August 29, 3009]); 

mise à jour:

j'ai pu obtenir ce travail grâce à la answer provided by Kendall Helmstetter Geln. Voici la méthode complète pour une gamme d'une semaine:

+ (DateRange *)rangeForWeekContainingDate:(NSDate *)date 
{ 
    DateRange * range = [[self alloc] init]; 

    // start of the week 
    NSDate * firstDay; 
    [[self calendar] rangeOfUnit:NSWeekCalendarUnit 
         startDate:&firstDay 
         interval:0 
         forDate:date]; 
    [range setStartDate:firstDay]; 

    // end of the week 
    NSDateComponents * oneWeek = [[NSDateComponents alloc] init]; 
    [oneWeek setWeek:1]; 
    [range setEndDate:[[self calendar] dateByAddingComponents:oneWeek 
                 toDate:firstDay 
                 options:0]]; 
    [oneWeek release]; 

    return [range autorelease]; 
} 
+2

Une chose que vous voudrez peut-être changer dans votre solution est d'avoir '[[auto alloc ] init] 'au lieu de' [[DateRange alloc ... ', de cette façon les sous-classes vont aussi s'attribuer, au lieu de toujours utiliser DateRange qui pourrait être leur superclasse. – jbrennan

+1

@jbrennan: bon point. Je l'ai changé. –

Répondre

2

Eh bien, puisque timeInterval est en quelques secondes, il suffit de le calcul pour savoir combien de secondes sont en un jour:

60 secondes * 60 minutes * 24 heures = 1 jour. Puis, dans votre méthode rangeForDayContainingDate, vous pouvez extraire les composants de date, obtenir le jour actuel, créer une nouvelle date en fonction du jour avec les heures et les minutes définies sur 0:00 et créer la date de fin en ajoutant l'intervalle de temps calculé au dessus.

+0

+1 Cela semble prometteur. Les composants de date pourraient être exactement ce que je cherchais. –

+0

Merci, monsieur! Votre réponse m'a indiqué dans la bonne direction. J'ai posté la solution complète pour une gamme d'une seule semaine comme un edit à la question originale. –

+0

Vous êtes les bienvenus, s'il vous plaît n'hésitez pas à marquer votre propre réponse comme la solution réelle au lieu de mes directions approximatives ... Je ne serai pas offensé. –

8

Par souci d'exhaustivité, voici ma solution finale (merci à Kendall Helmstetter Geln et jbrennan):

+ (NSCalendar *)calendar 
{ 
    NSCalendar * gregorian = [[NSCalendar alloc] 
           initWithCalendarIdentifier:NSGregorianCalendar]; 
    return [gregorian autorelease]; 
} 

//////////////////////////////////////////////////////////////// 

+ (NSDateComponents *)singleComponentOfUnit:(NSCalendarUnit)unit 
{ 
    NSDateComponents * component = [[NSDateComponents alloc] init]; 

    switch (unit) 
    { 
     case NSDayCalendarUnit: [component setDay:1]; break; 
     case NSWeekCalendarUnit: [component setWeek:1]; break; 
     case NSMonthCalendarUnit: [component setMonth:1]; break; 
     case NSYearCalendarUnit: [component setYear:1]; break; 
    } 

    return [component autorelease]; 
} 

//////////////////////////////////////////////////////////////// 

+ (WM_DateRange *)rangeForUnit:(NSCalendarUnit)unit 
       surroundingDate:(NSDate *)date 
{ 
    WM_DateRange * range = [[self alloc] init]; 

    // start of the period 
    NSDate * firstDay; 
    [[self calendar] rangeOfUnit:unit 
         startDate:&firstDay 
         interval:0 
         forDate:date]; 
    [range setStartDate:firstDay]; 

    // end of the period 
    [range setEndDate:[[self calendar] 
     dateByAddingComponents:[self singleComponentOfUnit:unit] 
         toDate:firstDay 
         options:0]]; 

    return [range autorelease]; 
} 

//////////////////////////////////////////////////////////////// 

+ (WM_DateRange *)rangeForDayContainingDate:(NSDate *)date 
{ return [self rangeForUnit:NSDayCalendarUnit surroundingDate:date]; } 

+ (WM_DateRange *)rangeForWeekContainingDate:(NSDate *)date 
{ return [self rangeForUnit:NSWeekCalendarUnit surroundingDate:date]; } 

+ (WM_DateRange *)rangeForMonthContainingDate:(NSDate *)date 
{ return [self rangeForUnit:NSMonthCalendarUnit surroundingDate:date]; } 

+ (WM_DateRange *)rangeForYearContainingDate:(NSDate *)date 
{ return [self rangeForUnit:NSYearCalendarUnit surroundingDate:date]; } 

//////////////////////////////////////////////////////////////// 

- (void)dealloc 
{ 
    [endDate release]; 
    [startDate release]; 
    [super dealloc]; 
} 
+0

Cela m'a beaucoup aidé sur un projet sur lequel je travaille - merci d'avoir posté votre réponse finale !! – Jim

Questions connexes