Вопрос

Привет,

Недавно я столкнулся с большой проблемой (как мне кажется) с классом NSCalendar.

В моей задаче мне нужно работать с большими периодами времени, начиная с 4000 г. до н.э. по 2000 г. н.э. (по григорианскому календарю).Где-то меня заставили увеличить какой-то NSDate на 100-летний интервал.При увеличении лет на временной шкале AD (0->...) все работало нормально, но когда я попробовал то же самое с BC, я был немного сбит с толку.

Проблема в том, что когда вы пытаетесь прибавить 100 лет к году 3000BC [отредактировано], вы получите 3100BC [отредактировано] несмотря ни на что...Лично мне это показалось странным и нелогичным.Правильный результат должен быть 2900BC.

Вот пример кода, чтобы вы могли увидеть это «неправильное» поведение:

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

// initing
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setYear:-1000];
NSDate *date = [gregorian dateFromComponents:comps];

// math
NSDateComponents *deltaComps = [[[NSDateComponents alloc] init] autorelease];
[deltaComps setYear:100];

date = [gregorian dateByAddingComponents:deltaComps toDate:date options:0];

// output
NSString *dateFormat = @"yyyy GG";

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:dateFormat];
NSLog(@"%@", [formatter stringFromDate:date]);

Что вы можете сказать о таком поведении?Так должно работать или это баг?Я в замешательстве :С.

КСТАТИ.:метод [NSCalendarComponents:fromDate:toDate:options:] не позволяет нам вычислить разницу между годами в эпоху до нашей эры...Дополнительный "почему?" В этой коробке Пандоры.

P.S.:Я копался в официальной документации и других ресурсах, но ничего не нашел по этой проблеме (или, может быть, так и задумано, а я идиот?).

Это было полезно?

Решение

Я нашел простое решение этой ошибки.Вот:

@interface NSCalendar (EraFixes)

- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts;

@end

@implementation NSCalendar (EraFixes)

- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts
{
    NSDateComponents *toDateComps = [self components:NSEraCalendarUnit fromDate:date];
    NSDateComponents *compsCopy = [[comps copy] autorelease];

    if ([toDateComps era] == 0) //B.C. era
    {
        if ([comps year] != NSUndefinedDateComponent) [compsCopy setYear:-[comps year]];
    }

    return [self dateByAddingComponents:compsCopy toDate:date options:opts];
}

@end

Если вам интересно, почему я инвертирую только годы, ответ прост: все остальные компоненты, кроме лет, увеличиваются и уменьшаются правильным образом (я не проверял их все, но месяцы и дни, похоже, работают нормально).

РЕДАКТИРОВАТЬ:удалено по ошибке добавлено автовыпуск, спасибо Джон.

Другие советы

Это ошибка и или функция. Apple Doc никогда не говорит, что они подразумевают под Добавление компонентов в календальную дату. Отказ Для них идеально свободно определить «добавление компонента» на дату BCE в качестве просто дополнения к компоненту года.

Да, я согласен с тобой, что это противоречит, и я думаю, что это ошибка.

Вам нужно преобразовать свой NSDate либо

  • второй из эпохи Unix (1.1.1970) с использованием -timeIntervalSince1970
  • второй из ОС X EPOCH (1.1.2001), используя -timeIntervalSinceReferenceDate

Затем вы можете выполнить расчет и преобразовать его обратно в NSDate. Отказ Я думаю, что это плохое представление о работе в Грегорьеском календаре все время ... Было бы лучше преобразовать в Грегорианский календарь незадолго до того, как покажешь его на графическом интерфейсе.

Представьте, что у вас есть дата с 1-м моментом нашей эры - AD 0001-01-01 00:00:00. Какой был момент раньше? BC 0001-01-01 00:00:01.. Отказ Если разработчики какао использовали базовые арифметики для этой задачи, вы получите AD 0000-12-31 23:59:59.. Отказ Это разумно для григорианского календаря? Я думаю, нет. Итак, мне кажется, что самый удобный способ реализации календаря должен был использовать флаг эпохи и изменения »направление времени«При работе с эпохи BC, чтобы получить читаемые человеком даты в каждом случае.

КСТАТИ.: [NSCalendar dateByAddingComponents:toDate:options:] Действительно ведет себя странно и не может рассчитывать интервал времени между датами BC, я тоже проверил. Итак, для даты BC вы можете использовать обходной путь, например, путем перевода датов на AD, а затем найти diff.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top