Получение странных результатов от NSDateComponentsFormatter

Недавно я узнал о новом для iOS8 классе NSDateComponentsFormatter. Это позволяет вам генерировать временные строки для временных интервалов, а не для дат. Довольно круто. Я решил повозиться с этим и написал тестовый код, который создает различные промежутки времени и регистрирует вывод. Вот мой код (вывод на английском и французском языках)

  NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
  
  
  NSDateComponentsFormatter* formatter = [[NSDateComponentsFormatter alloc] init];
  formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
  formatter.calendar = gregorian;
  
  formatter.allowedUnits = NSCalendarUnitYear + NSCalendarUnitMonth + NSCalendarUnitDay;
  
  NSDateComponents *components = [[NSDateComponents alloc] init];
  for (int years = 1; years <= 10; years++)
  {
    int days = arc4random_uniform(10);
    components.year = years;
    components.month = 3;
    components.day = days;
    NSString* outputString = [formatter stringFromDateComponents: components];
    NSLog(@"For %02d years %02d days, Date Components string = '%@'", years, days, outputString);
  }

  NSLocale *franceLocale = [NSLocale localeWithLocaleIdentifier: @"fr_FR"];
  gregorian.locale = franceLocale;
  formatter.calendar = gregorian;

  NSLog(@"--------------- French. --------------");
  for (int years = 1; years <= 10; years++)
  {
    int days = arc4random_uniform(10) ;

    components.year = years;
    components.day = days;

    NSString* outputString = [formatter stringFromDateComponents: components];
    NSLog(@"For %02d years %02d days, Date Components string = '%@'", years, days, outputString);
  }

(Я не регистрирую значение месяца, так как оно фиксировано.)

Вот результат:

For 01 years 00 days, Date Components string = '1 year, 3 months'
For 02 years 05 days, Date Components string = '2 years, 3 months, 5 days'
For 03 years 01 days, Date Components string = '3 years, 3 months'
For 04 years 06 days, Date Components string = '4 years, 3 months, 6 days'
For 05 years 07 days, Date Components string = '5 years, 3 months, 7 days'
For 06 years 02 days, Date Components string = '6 years, 3 months, 1 day'
For 07 years 04 days, Date Components string = '7 years, 3 months, 4 days'
For 08 years 02 days, Date Components string = '8 years, 3 months, 2 days'
For 09 years 08 days, Date Components string = '9 years, 3 months, 8 days'
For 10 years 03 days, Date Components string = '10 years, 3 months, 2 days'
--------------- French. --------------
For 01 years 02 days, Date Components string = '1 année, 3 mois et 2 jours'
For 02 years 02 days, Date Components string = '2 années, 3 mois et 2 jours'
For 03 years 05 days, Date Components string = '3 années, 3 mois et 5 jours'
For 04 years 03 days, Date Components string = '4 années, 3 mois et 3 jours'
For 05 years 04 days, Date Components string = '5 années, 3 mois et 4 jours'
For 06 years 04 days, Date Components string = '6 années, 3 mois et 4 jours'
For 07 years 04 days, Date Components string = '7 années, 3 mois et 3 jours'
For 08 years 08 days, Date Components string = '8 années, 3 mois et 8 jours'
For 09 years 05 days, Date Components string = '9 années, 3 mois et 5 jours'
For 10 years 02 days, Date Components string = '10 années, 3 mois et 2 jours'

Обратите внимание, что в некоторых случаях выходное значение дней в выходных данных средства форматирования не соответствует введенному в него значению дней.

Кто-нибудь знает, что здесь происходит не так? Для меня это очень похоже на ошибку ОС/фреймворка.

РЕДАКТИРОВАТЬ:

Я запустил свой тестовый код в приложении Mac под OS X версии 10.10.5. Кто-нибудь еще использует 10.10.5 и может ли он попробовать?

Я также получил один неправильный ответ против 8.1 sim. (Для входного значения 07 лет, 3 месяца, 06 дней, строка компонентов даты = «7 лет, 3 месяца, 5 дней»)


person Duncan C    schedule 27.02.2016    source источник
comment
Системная информация? Я не воспроизвел это в нескольких попытках, запущенных в OS X или на симуляторах 8.4 или 9.2.   -  person jscs    schedule 28.02.2016
comment
Из любопытства, что такое языковой стандарт системы и календарь?   -  person Ken Thomases    schedule 28.02.2016
comment
Язык системы — американский английский. Системный календарь — григорианский. Я запускаю этот код в OS X под 10.10.5.   -  person Duncan C    schedule 28.02.2016
comment
Если я помещу тот же код в проект симулятора iOS, он, кажется, будет безупречно работать с 9.2, но я получил 1 неправильную строку, запускающую этот код на iOS 8.1. сим. Начинает выглядеть как ошибка конкретной ОС.   -  person Duncan C    schedule 28.02.2016
comment
Я вижу странные результаты, подобные вашим, на 10.10.x, а не на 10.11.x. Может быть ошибка. Также может быть, что некоторые вещи не были указаны, и поведение было допустимым, просто неожиданным. Посмотрите, поможет ли заполнение дополнительных свойств компонентов или средства форматирования. Например, компоненты также могут иметь calendar или timeZone.   -  person Ken Thomases    schedule 28.02.2016
comment
То, как я читал документы, вы выбираете единицы, которые вам интересны, и генерирует строку, описывающую промежуток времени в этих единицах. Я не понимаю, как неправильное количество дней действительно.   -  person Duncan C    schedule 28.02.2016
comment
Это все больше и больше похоже на ошибку OS X 10.10/iOS 8. Apple УЖАСНО исправляет ошибки в предыдущих выпусках ОС. Как только выйдет новый крупный релиз, я думаю, что мы застряли с ним.   -  person Duncan C    schedule 28.02.2016


Ответы (1)


Похоже, что версия NSDateComponentsFormatter для iOS 8.x и Mac OS 10.10 содержит ошибки. Я получаю (периодически!) разные, неправильные результаты для некоторых дат в этих версиях ОС, но правильные результаты для последних версий ОС.

Вздох...

person Duncan C    schedule 04.03.2016
comment
NSDateComponentsFormatter основан на NSCalendar. Он также учитывает переход на летнее время. - person vadian; 04.03.2016