Компоненты NSCalendar без учета времени

Мы знаем, что NSDate - это UTC / GMT. Другими словами, с ним не связана никакая информация о часовом поясе.

Существуют классы высокого уровня, такие как NSCalendar, NSTimeZone и NSDateComponents, которые учитывают часовой пояс.

Исходя из этого, я использую следующий код для вычисления разницы в днях между двумя датами. Однако результат, который я получаю, кажется, так как расчет выполняется без учета времени. Мне интересно, делаю ли я что-то не так или это по какой-то причине задумано.

Вот код и данные:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comp = [calendar components:NSDayCalendarUnit fromDate:startDate toDate:stopDate options:0];
NSInteger day = [comp day];

Вывод отладки:

(gdb) po startDate
2011-04-01 03:52:13 +0000
(gdb) po stopDate
2011-04-03 15:52:13 +0000
(gdb) p (int) day
$1 = 2

Часовой пояс - стандартное тихоокеанское время, а даты, указанные выше, преобразованы в стандартное тихоокеанское время:

startDate = 2011-03-31 8:52:13 -7
stopDate  = 2011-04-03 8:52:13 -7

Поэтому я бы ожидал, что между ними будет 4 дня, а не 2 (31-е, 1-е, 2-е и 3-е).

Я думаю, что часы игнорируются, потому что если добавить часы к вычислениям, мы получим 2 дня и 12 часов.

Я что-то делаю не так или это так, как задумано?

Спасибо, Вэнс


person vance    schedule 01.04.2011    source источник


Ответы (1)


Не совсем. Когда вы форматируете даты в часовом поясе Тихого океана, вы получаете:

Calendars[38041:707] start: 2011-03-31 20:52:13 -0700
Calendars[38041:707] stop : 2011-04-03 08:52:13 -0700

Это немного отличается от того, что вы опубликовали. Кажется, у вас 8 утра, а не 8 вечера.

Кроме того, components:fromDate:toDate:options: будет считать целые единицы. Таким образом, если вы спрашиваете количество дней, будет сказано, что между ними есть 2 полных дня, которые и есть.

Возможно, лучший способ сделать то, что вы ищете, - это:

NSUInteger startOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:startDate];
NSUInteger stopOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:stopDate];

Тогда количество дней между ними будет (stopOrdinal - startOrdinal). В случае ваших дат это дает 3 (1 апреля по Гринвичу - 3 апреля по Гринвичу). Если вы действительно хотите игнорировать временную часть, вам придется выяснить, как отрезать временную часть дат в целевом часовом поясе. Это будет включать преобразование дат в объекты NSDateComponent, а затем установку частей -hour, -minute и -second на 0. Как только вы это сделаете, вы можете изменить их обратно на NSDates, а затем продолжить вычисления разницы.

person Dave DeLong    schedule 20.11.2011