Дата с 1600 до NSDate? - PullRequest
       45

Дата с 1600 до NSDate?

1 голос
/ 12 января 2011

У меня есть дата, которая с 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];

(я никогда не изменяю значения в смещении где-либо еще.)

Проблема в том, что яу меня другое время для 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, и что мне с этим делать?(Я предполагаю, что разница в часах равна летнему времени.)

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

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

Ответы [ 3 ]

3 голосов
/ 12 января 2011

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

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

1 голос
/ 12 января 2011

Похоже, правильный ответ - сделать вещи проще. Вместо создания 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. Пользователи используют меньше иваров.
  2. Это меньше кода.
  3. Он всегда возвращает полночь в этот день, независимо от того, действует ли DST.
0 голосов
/ 22 января 2015

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

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

...