iPhone - получить количество дней между двумя датами

Я пишу приложение GTD для iPhone. Для должных задач я хочу отобразить что-то вроде «Должно завтра» или «Должно вчера» или «Должно 18 июля». Очевидно, что мне нужно отобразить «Завтра», даже если до задания осталось менее 24 часов (например, пользователь проверяет в 23:00 в субботу и видит, что есть задание в воскресенье в 8:00). Итак, я написал метод, чтобы получить количество дней между двумя датами. Вот код ...

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;
}

Ответы на вопрос(7)

Ваш ответ на вопрос