Вопрос

Я пытался найти разумный способ хранения ежедневных данных с помощью Core Data на iPhone.

Мое приложение получает данные в формате csv с датой, но без времени:

date, cycles
2009-08-01, 123
2009-08-02, 234
2009-08-03, 345
2009-08-04, 456

При хранении этих данных в день должна быть только одна запись.Я решил, что лучше всего создать NSDate для хранения, но удалить данные о времени и часовом поясе.

Я могу легко создать NSDate без часов, минут или секунд, используя NSDateComponents или NSDateFormatter.Однако даже когда я явно устанавливаю часовой пояс в формате UTC или в ноль секунд от GMT, выводя созданную дату с помощью NSLog() всегда имеет мой местный часовой пояс, например:

2009-07-29 00:00:00 +0100

Кто-нибудь знает лучший способ создания NSDates без компонентов времени?Или, возможно, лучший способ хранения дат?

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

Решение

Хорошее практическое правило программирования — всегда хранить даты в формате UTC.Не имеет значения, используете ли вы Core Data или нет;вам все равно придется поработать, потому что классы дат Apple в значительной степени отстой.

Даты внутренне представлены как количество секунд с исходной даты, которая, как я полагаю, соответствует 00:00:00 1 января 2001 г. (хотя фактическая исходная дата не очень важна).Дело в том, NSDate объекты всегда изначально находятся в формате UTC.Если даты, которые вы получаете в своем CSV-файле, являются локальными, вам нужно будет сделать что-то вроде этого, чтобы получить время UTC:

NSDate *UTCDate = [localDate addTimeInterval:-[[NSTimeZone localTimeZone] secondsFromGMT]];

Затем я бы установил время на 00:00:00.Теперь вы сохраняете дату в полночь в формате UTC.В целях презентации вы будете использовать NSDateFormatter настроен с часовым поясом по вашему выбору (часовой пояс системы используется по умолчанию, если вы его не укажете) для отображения этих дат.

Однако часовые пояса не имеют особого значения, когда вы имеете дело просто с датами.Если вы обязательно установили часовой пояс на своем NSDateFormatter в UTC, вы всегда будете показывать одну и ту же дату, независимо от того, какой часовой пояс выбрал пользователь на своем устройстве.

Если вам не нравится это решение, вы всегда можете сохранить даты в альтернативном формате.Вы можете использовать double или int чтобы сохранить дату в каком-либо пользовательском формате (например,количество дней, прошедших с некоторой исходной даты), или вы даже можете создать свой собственный класс, чтобы смоделировать дату именно так, как вы хотите, и сохранить ее как NSData объект.Пока класс реализует NSCoding, вы можете сериализовать его в NSData объект в Core Data.Вам просто нужно установить тип атрибута в Core Data на «Transformable».

Здесь у вас есть масса вариантов, и ни один из них не требует усилий по написанию собственных запросов и баз данных SQLite.

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

NSDate не имеет часового пояса. NSLog использует ваш местный часовой пояс; там написано +0100, потому что ты там.

Объект NSDate всегда будет включать дату времени - чтобы процитировать документы, которые он "представляет [s] на один момент времени"; и делает это, сохраняя значение времени с его контрольной даты (начало 1 января 2001 года в GMT, опять-таки в соответствии с документами). Поэтому у вас не может быть NSDate, который не знает времени суток.

Вместо того, чтобы пытаться хранить даты по-своему, я все равно использовал бы NSDate в вашей модели и рассмотрел бы добавление пары методов в ваш класс сущностей, один из которых будет делать то, что вы описали выше, устанавливая NSDate в 00:00. : 00 в данный день. Другой может вернуть только дату из NSDate в вашем предпочтительном формате. Затем они будут использовать сгенерированные Core Data методы получения и установки для доступа к свойству NSDate.

Продолжая использовать NSDate, вы используете класс, с которым Core Data может работать изначально, а это означает, что вы все равно можете легко использовать предикаты для фильтрации или сортировать полученные результаты по дате, не задумываясь об этом.

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