2009-08-25 34 views
5

我创建可可的报告生成器,我需要制作方便的日期范围,如“今天”,“本周”,“这个月”,“今年”,等等。如何根据给定的NSDate生成方便的日期范围?

是否有好办法做到这一点?这里是我的骨架迄今:

@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 

一些示例用例将如下所示:

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

从本质上讲,我想返回DateRange对象包含一周的开始和结束日期,月或目标日期周围的一年。例如(在伪代码):

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

更新:

我能得到这个工作,感谢answer provided by Kendall Helmstetter Geln。这里是一个星期的范围完整的方法:

+ (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

有一件事你可能想在您的解决方案改变是有'[[自我ALLOC ] init]'而不是'[[DateRange alloc ...',这样子类也会自己分配,而不是总是使用DateRange,它可能是它们的超类。 – jbrennan 2009-08-25 21:53:09

+1

@ jbrennan:好点。我改变了它。 – 2009-08-25 23:56:56

回答

2

好,因为一个时间间隔为秒,只是做数学题,找出多少秒一天:

60秒*60分钟* 24小时= 1天。

然后在您的rangeForDayContainingDate方法中,您可以提取日期组件,获取当前日期,基于时间和分钟设置为0:00的日期创建新日期,并创建结束日期,将时间间隔添加为计算的以上。

+0

+1看起来很有希望。日期组件可能正是我所需要的。 – 2009-08-25 21:06:31

+0

谢谢,先生!你的回答指出我的方向是正确的。作为对原始问题的修改,我已发布了单周范围的完整解决方案。 – 2009-08-25 21:46:30

+0

不客气,请随时将自己的答案标记为实际的解决方案,而不是我粗略的方向......我不会被冒犯。 – 2009-08-26 18:13:44

8

为了完整起见,这里是我的最终解决方案(与感谢肯德尔黑尔姆施泰特Geln和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

这对我正在开发的一个项目帮助很大 - 感谢您发布您的最终答案! – Jim 2011-09-21 22:09:32