我正在为iPhone编写一个GTD应用程序.对于应有的任务,我希望显示诸如“明天到期”或“到期日”或“到期7月18日”之类的内容.显然,即使任务距离不到24小时,我也需要显示“明天”(例如,用户在星期六晚上11点检查,并在周日早上8点看到任务).所以,我写了一个方法来获取两个日期之间的天数.这是代码……
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd-HH-mm"]; NSDate *NowDate = [dateFormatter dateFromString:@"2010-01-01-15-00"]; NSDate *dueDate = [dateFormatter dateFromString:@"2010-01-02-14-00"]; NSLog(@"NSDate *NowDate = %@",NowDate); NSLog(@"NSDate *dueDate = %@",dueDate); NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *differenceComponents = [calendar components:(NSDayCalendarUnit) fromDate:NowDate toDate:dueDate options:0]; NSLog(@"Days between dates: %d",[differenceComponents day]);
……这是输出:
NSDate *NowDate = 2010-01-01 15:00:00 -0700 NSDate *dueDate = 2010-01-02 14:00:00 -0700 Days between dates: 0
如您所见,该方法返回不正确的结果.它应该返回1作为两天之间的天数.我在这做错了什么?
编辑:我写了另一种方法.我没有进行过广泛的单元测试,但到目前为止似乎有效:
+ (NSInteger)daysFromDate:(NSDate *)fromDate inTimeZone:(NSTimeZone *)fromTimeZone untilDate:(NSDate *)toDate inTimeZone:(NSTimeZone *)toTimeZone { NSCalendar *calendar = [NSCalendar currentCalendar]; unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; [calendar setTimeZone:fromTimeZone]; NSDateComponents *fromDateComponents = [calendar components:unitFlags fromDate:fromDate]; [calendar setTimeZone:toTimeZone]; NSDateComponents *toDateComponents = [calendar components:unitFlags fromDate:toDate]; [calendar setTimeZone:[NSTimeZone defaultTimeZone]]; NSDate *adjustedFromDate = [calendar dateFromComponents:fromDateComponents]; NSDate *adjustedToDate = [calendar dateFromComponents:toDateComponents]; NSTimeInterval timeIntervalBetweenDates = [adjustedToDate timeIntervalSinceDate:adjustedFromDate]; NSInteger daysBetweenDates = (NSInteger)(timeIntervalBetweenDates / (60.0 * 60.0 * 24.0)); NSDateComponents *midnightBeforeFromDateComponents = [[NSDateComponents alloc] init]; [midnightBeforeFromDateComponents setYear:[fromDateComponents year]]; [midnightBeforeFromDateComponents setMonth:[fromDateComponents month]]; [midnightBeforeFromDateComponents setDay:[fromDateComponents day]]; NSDate *midnightBeforeFromDate = [calendar dateFromComponents:midnightBeforeFromDateComponents]; [midnightBeforeFromDateComponents release]; NSDate *midnightAfterFromDate = [[NSDate alloc] initWithTimeInterval:(60.0 * 60.0 * 24.0) sinceDate:midnightBeforeFromDate]; NSTimeInterval timeIntervalBetweenToDateAndMidnightBeforeFromDate = [adjustedToDate timeIntervalSinceDate:midnightBeforeFromDate]; NSTimeInterval timeIntervalBetweenToDateAndMidnightAfterFromDate = [adjustedToDate timeIntervalSinceDate:midnightAfterFromDate]; if (timeIntervalBetweenToDateAndMidnightBeforeFromDate < 0.0) { // toDate is before the midnight before fromDate timeIntervalBetweenToDateAndMidnightBeforeFromDate -= daysBetweenDates * 60.0 * 60.0 * 24.0; if (timeIntervalBetweenToDateAndMidnightBeforeFromDate < 0.0) daysBetweenDates -= 1; } else if (timeIntervalBetweenToDateAndMidnightAfterFromDate >= 0.0) { // toDate is after the midnight after fromDate timeIntervalBetweenToDateAndMidnightAfterFromDate -= daysBetweenDates * 60.0 * 60.0 * 24.0; if (timeIntervalBetweenToDateAndMidnightAfterFromDate >= 0.0) daysBetweenDates += 1; } [midnightAfterFromDate release]; return daysBetweenDates; }
解决方法
从组件的文档:fromDate:toDate:options ::
The result is lossy if there is not a small enough unit requested to hold the full precision of the difference.
由于差异小于一整天,因此它正确返回0天的结果.