NSDate月加法和减法

时间:2010-11-08 14:10:21

标签: iphone objective-c ios

我有一个班级,其中包含开始日期和结束日期,通常初始化为该月的最后一天和最后一秒。

以下功能可以正常运行,从2010年11月开始到12月再返回,但是从11月开始向后,最后将startDate设置为

  

2010-09-30 23:00:00 GMT

IE中。一个月一小时前。

奇怪的是,endDate仍然正确设置为

  

2010-11-01 00:00:00 GMT

从这个不正确的日期前进一个月也会产生正确的时间和日期。

这是一个错误还是我在做一些我不应该做的事情?

-(void) moveMonth:(NSInteger)byAmount { // Positive or negative number of months
    NSCalendar *cal = [NSCalendar currentCalendar];

 NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
 // Update the start date
 [components setMonth:byAmount];
 NSDate *newStartDate = [cal dateByAddingComponents:components toDate:[self startDate] options:0];
 [self setStartDate:newStartDate];

 // And the end date
 [components setMonth:1];
 NSDate *newEndDate = [cal dateByAddingComponents:components toDate:[self startDate] options:0 ];
 [self setEndDate:newEndDate];
}

解决方案:正确回答指出这是DST问题

如果您想要处理绝对时间和日期,那么使用以下内容可以避免涉及任何DST。

    NSCalendar *cal = [[NSCalendar alloc ] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    NSTimeZone *zone = [NSTimeZone timeZoneWithName:@"GMT"];
    [cal setTimeZone:zone];

3 个答案:

答案 0 :(得分:5)

这可能不是一个错误,而是与10月至11月期间DST变化有关的事情。

答案 1 :(得分:1)

只需抓住当前日期的月份和年份,添加/减去月份差异,然后根据这些新值生成日期就更容易了。无需担心夏令时变化,闰年等等。这样的事情应该有效:

-(void) moveMonth:(NSInteger)byAmount {
    NSDate *now = [NSDate date];
    NSCalendar *cal = [NSCalendar currentCalendar];

    // we're just interested in the month and year components
    NSDateComponents *nowComps = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit) 
                                        fromDate:now];
    NSInteger month = [nowComps month];
    NSInteger year = [nowComps year];

    // now calculate the new month and year values
    NSInteger newMonth = month + byAmount;

    // deal with overflow/underflow
    NSInteger newYear = year + newMonth / 12;
    newMonth = newMonth % 12;

    // month is 1-based, so if we've ended up with the 0th month, 
    // make it the 12th month of the previous year
    if (newMonth == 0) {
        newMonth = 12;
        newYear = newYear - 1;
    }

    NSDateComponents *newStartDateComps = [[NSDateComponents alloc] init];
    [newStartDateComps setYear: year];
    [newStartDateComps setMonth: month];
    [self setStartDate:[cal dateFromComponents:newDateComps]];
    [newDateComps release];

    // Calculate newEndDate in a similar fashion, calling setMinutes:59, 
    // setHour:23, setSeconds:59 on the NSDateComponents object if you  
    // want the last second of the day
}

答案 2 :(得分:0)

这是一种正确的方法。此方法在添加/减去month" byAmount"之后返回新的NSDate。

-(NSDate*) moveMonth:(NSInteger)byAmount {

    NSDate *now = [NSDate date];

    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setMonth:byAmount];

    NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:now options:0];

    return newDate;
}