8

我在这里找到了计算两个日期之间天数差异的代码。
我写了一个方法:

-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
{
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];
    NSInteger startDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
                                            inUnit: NSEraCalendarUnit forDate:startDate];
    NSInteger endDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
                                          inUnit: NSEraCalendarUnit forDate:endDate];
    return endDay-startDay;
}

这种方法有一个问题:它不能考虑时区的事情。即使我添加这样的一行:

[gregorian setTimeZone:[NSTimeZone localTimeZone]];

我的测试代码是这样的:

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *strDate = @"2012-09-03 23:00:00";
    NSDate *dateStart = [dateFormat dateFromString:strDate];
    strDate = @"2012-09-04 01:00:00";
    NSDate *dateEnd = [dateFormat dateFromString:strDate];
    NSLog(@"Days difference between %@ and %@  is:  %d days",[dateFormat stringFromDate:dateStart],[dateFormat stringFromDate:dateEnd],[self daysWithinEraFromDate:dateStart toDate:dateEnd]);

结果是:

2012-09-03 23:00:00 和 2012-09-04 01:00:00 之间的天数差异为:0 天

我想通过两个日期之间的午夜数得到 1 天。我的时区是 GMT +8。但是这个计算是基于格林威治标准时间的,所以我得到了错误的天数。有没有办法解决这个问题?谢谢你。


Scott Lemmon的方法可以解决我的问题。我像这样重写我的代码:

-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
{
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];
    [gregorian setTimeZone:[NSTimeZone localTimeZone]];
    NSDate *newDate1 = [startDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
    NSDate *newDate2 = [endDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];

    NSInteger startDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
                                            inUnit: NSEraCalendarUnit forDate:newDate1];
    NSInteger endDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
                                          inUnit: NSEraCalendarUnit forDate:newDate2];
    return endDay-startDay;
}
4

2 回答 2

5

如果时区偏移不起作用,那么手动添加或减去它怎么样?

在您的情况下NSDate *newDate = [oldDate dateByAddingTimeInterval:(-8 * 60 * 60)];,减去您的 +8 小时。

或者,如果您也想自动查找 GMT 偏移量,那么它就是NSDate *newDate = [oldDate dateByAddingTimeInterval:(-[[NSTimeZone localTimeZone] secondsFromGMT])

另一个想法:一个可能更简单的解决方案是完全忽略时间信息。只需将两个日期设置为相同的任意数字,那么只要日期来自同一时区,无论格林威治标准时间偏移如何,您将始终获得正确的午夜数。

于 2012-09-04T07:01:44.353 回答
3

您真正想要的是NSDate方法timeIntervalSinceDate:,并获取该结果,如果它大于 0 但小于 86400(一天中的秒数),那就是一天。否则,将您的结果除以 86400,您将得到天数。

按照您目前拥有代码的方式,两天之间只有 2 小时,这就是为什么您看到的结果是 0 而不是 1。

编辑 - 为了确定是否发生了午夜,让我们试试我刚刚写下的这个函数:

- (NSDate *) getMidnightDateFromDate: (NSDate *) originalDate
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSIntegerMax fromDate:originalDate];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond:0];
    NSDate *midnight = [[NSCalendar currentCalendar] dateFromComponents:components];
    return(midnight);
}

- (BOOL) howManyDaysDifferenceBetween: startDate and: endDate
{
    NSDate * firstMidnight = [self getMidnightDateFromDate: startDate];
    NSDate * secondMidnight = [self getMidnightDateFromDate: endDate];
    NSTimeInterval timeBetween = [firstMidnight timeIntervalSinceDate: secondMidnight];

    NSInteger numberOfDays = (timeBetween / 86400);

    return(numberOfDays);
}

我基于Dave Delong 对这个问题的回答。不能保证我的代码会起作用(我没有测试它),但我认为这个概念是合理的。

于 2012-09-04T06:38:07.973 回答