Вопрос

У меня есть дата, которая хранится в виде количества дней с 1 января 1600 года, с которой мне нужно разобраться.Это устаревший формат даты, который мне нужно читать много-много раз в моем приложении.

Ранее я создавал календарь, пустые компоненты даты и корневую дату следующим образом:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
id rootComponents = [[[NSDateComponents alloc] init] autorelease];
[rootComponents setYear: 1600];
[rootComponents setMonth: 1];
[rootComponents setDay: 1];
self.rootDate = [gregorian dateFromComponents: rootComponents];
self.offset = [[[NSDateComponents alloc] init] autorelease];

Затем, чтобы позже преобразовать целое число в дату, я использую это:

[offset setDay: theLegacyDate];
id eventDate = [gregorian dateByAddingComponents: offset
                                          toDate: rootDate
                                         options: 0];

(Я никогда больше нигде не меняю никаких значений в offset.)

Проблема в том, что у меня другое время для rootDate на iOS противMac OS X.В Mac OS X приближается полночь.На iOS я получаю 8: 12: 28.(Пока, кажется, это согласуется с этим.) Когда я добавляю свое количество дней спустя, странное время остается.

OS       | legacyDate | rootDate                  | eventDate
======== | ========== | ==========================|==========================
Mac OS X | 143671     | 1600-01-01 00:00:00 -0800 | 1993-05-11 00:00:00 -0700
iOS      | 143671     | 1600-01-01 08:12:28 +0000 | 1993-05-11 07:12:28 +0000

В предыдущем выпуске моего продукта я не заботился о времени;теперь я знаю.Почему такое странное время на iOS, и что мне с этим делать?(Я предполагаю, что разница в часах равна DST.)

Я попытался установить час, минуту и секунду ROOTCONTENTS равными 0.Это не оказывает никакого влияния.Если я установлю для них значение, отличное от 0, это добавит их к 8:12:28.Мне было интересно, связано ли это как-то с високосными секундами или другими кумулятивными изменениями часов.

Или это совершенно неправильный подход для использования на iOS?

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

Решение 2

Похоже, правильный ответ заключается в том, чтобы упростить задачу.Вместо того чтобы создавать rootDate, я просто каждый раз создаю дату из компонентов.Это не должно быть медленнее, и это по-прежнему делает код действительно близким к идее.

Начальная настройка:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
self.components = [[[NSDateComponents alloc] init] autorelease];
[components setYear: 1600];
[components setMonth: 1];

(Очевидно, что свойства и ивары скорректированы.)

Позже, чтобы фактически преобразовать устаревшую дату в NSDate:

[components setDay: 1 + theLegacyDate];
id eventDate = [gregorian dateFromComponents: components];

Для меня это имеет следующие преимущества:

  1. В нем используется меньше ivar-файлов.
  2. Это меньше кода.
  3. Он всегда возвращает полночь в этот день, независимо от того, действует ли летнее время.

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

Я полагаю, вы правы насчет високосных секунд / кумулятивных изменений часов, учитывающих проблему времени.Действительно ли даты, с которыми вы имеете дело, относятся к прошлому, или это чисто произвольная эпоха?

В любом случае, вы могли бы попробовать определить новую эпоху, которая намного ближе к сегодняшнему дню (скажем, эпоху Какао).Вычислите разницу в сутках между новой эпохой и старой и сохраните ее как константу.Когда вам нужно обработать дату, примените эту дельту к дате, а затем используйте свой существующий метод NSCalendar, но с вашей новой эпохой вместо старой.Надеемся, это позволит избежать проблемы с дрейфом часов, которую вы наблюдаете.

Обратите внимание, что iOS учитывает очень неясные правила для различных часовых поясов.Скорее всего, в полночь, 1 января.1600 в вашем часовом поясе на самом деле было в 7:12:28 UTC.Было много случаев, когда люди жаловались на ошибки в преобразовании дат, а затем кто-то выяснял, что на самом деле они находятся в часовом поясе, в котором много лет назад произошли какие-то странные изменения в календаре.

Сначала вам нужно выяснить, какой именно NSDate представляют ваши данные."Количество дней с 1 января 1600 года" - это чепуха, потому что вам нужен часовой пояс!Что вы должны сделать:Найдите "устаревшее" число, по которому вы знаете, какой день оно должно обозначать.Например, если вы "знаете", что 143671 в вашем часовом поясе должен быть 11 мая 1993 года, то начните с этой даты в качестве корневой и добавьте к ней (x - 143671) дней.

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