WedX - журнал о программировании и компьютерных науках

Игнорирование изменений часового пояса после сохранения NSDate

Мои приложения не зависят от часового пояса: я хочу, чтобы дата и время сохранялись и отображались таким образом, чтобы игнорировать изменения часового пояса пользователя. После того, как я записал локальную дату / время некоторого действия пользователя в моем приложении (обычно путем сохранения timeIntervalSince1970 в базе данных sqlite), я хочу показать ту же строку даты / времени независимо от того, изменился ли часовой пояс пользователя или нет, и независимо от различных настроек часового пояса пользователя на его устройстве.

Например, если действие пользователя происходит в 13:15 по местному времени в Сан-Франциско, а затем он открывает мое приложение через несколько дней в Нью-Йорке, я хочу, чтобы это предыдущее действие по-прежнему отображалось как 13:15 (а не 4: 15 часов вечера), и даже если он вручную установил другой часовой пояс на своем устройстве (например, Чикаго). Второе действие в Нью-Йорке в 21:00 там навсегда должно отображаться как 21:00, даже когда вы вернетесь в Калифорнию.

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

Как я могу быть независимым от часового пояса при сохранении и извлечении даты / времени?

(Кажется, что приложение Apple Calendar ведет себя таким образом, когда включено изменение часового пояса, но только если я вручную установил время события.)

27.01.2015

  • Вы можете обмануть и сделать так, чтобы ваши значения NSDate всегда относились к местному часовому поясу (т. Е. Всегда устанавливали форматировщик на UTC, независимо от местного часового пояса). Однако есть драконы. 31.01.2015
  • Вы имеете в виду сделать это при запуске: [NSTimeZone setDefaultTimeZone: [NSTimeZone timeZoneWithName: @ America / Chicago]]; - да, есть драконы. Если я сделаю это и использую приложение в другом часовом поясе, время будет сохранено, как если бы я был в Чикаго. Если мое действие происходит в 14:00 во Флориде (на моем iPad отображается время во Флориде) и я сохраняю результат [[NSDate date] timeIntervalSince1970], приложение отображает действие как происходящее в 13:00. 31.01.2015
  • Нет, я имею в виду, что всегда устанавливайте форматировщик даты на UTC перед использованием. Тогда любое время, которое вы введете, будет повторно отображаться точно в то же время, когда вы NSLog NSDate, без смещения часового пояса. Но (среди прочего) вам нужно сделать swizzle, когда вы фиксируете текущее время с помощью [NSDate date]. 31.01.2015
  • @Hot Licks - пожалуйста, расскажите подробнее о своей сладости. Я не понимаю, как вы планируете убрать зависимость TZ - фокус в том, чтобы правильно фиксировать дату. Это моя проблема. 09.02.2015
  • При преобразовании символьной даты в NSDate используйте UTC. Затем, когда вы берете текущее время с помощью [NSDate date], вам нужно как-то преобразовать это в местное время - проще всего использовать dateFormatter, установленный на локальный TZ, для преобразования в char, затем dateFormatter, установленный на UTC, чтобы преобразовать обратно в NSDate. (Но поймите, что это нестандартно.) 09.02.2015
  • @ Hot Licks. Я отчаянно пытаюсь понять ваш комментарий о UTC, но он ускользает от меня. Сначала я создаю дату, используя [NSDate date], и ​​после этого я всегда хочу отображать ее как время на часах в месте захвата, независимо от текущего TZ iPad. Если вы предлагаете сохранить дату в виде строки, я понимаю, что мне нужно сначала отформатировать ее, используя местный часовой пояс. Итак, зачем мне конвертировать в UTC? Сохранение строки будет работать (но похоже на кладж) или сохранить timeIntervalSince1970 И тогдашний локальный TZ (вероятно, лучший способ). 09.02.2015
  • Я просто говорю, что самый простой способ получить объект NSDate, содержащий теперь внутреннюю запись в локальном времени по сравнению с UTC, - это преобразовать значение [NSDate date] в форму char с помощью средства форматирования даты, установленного в вашем часовом поясе, а затем немедленно преобразовать обратно в NSDate, используя форматировщик даты, установленный на UTC. Есть более изящные способы, но еще более запутанные. (Как я уже сказал, использование объектов NSDate, отражающих местное время, имеет некоторые подводные камни.) 09.02.2015
  • @Hot Licks - сейчас я понимаю вашу идею: (1) преобразовать любой [NSDate date] в строку, используя форматтер, установленный на systemTimeZone (эта строка будет соответствовать местному времени), (2) преобразовать эту строку обратно в значение даты, используя форматировщик установлен на GMT, (3) сохранить это значение в базе данных (нет необходимости сохранять TZ в базе данных, поскольку с этого момента локальная TZ будет игнорироваться). (4) Позже, когда значение даты извлекается из БД, преобразуйте его в строку, используя средство форматирования даты, установленное на GMT (но не показывайте никаких TZ в строке). - Если вы создадите ответ, в котором говорится, что (скопируйте / вставьте, хорошо), я приму его. 18.02.2015

Ответы:


1

Вот рабочее решение (@Hot Licks заслуживает похвалы, но он не опубликовал ответа):

  1. Создайте подкласс NSDate и добавьте метод gmtDate, который выполняет преобразование из местного TZ в GMT. gmtDate использует @"yyyy-MM-dd HH:mm" как строку формата, которая также отбрасывает секунды от значения. Нравится:
+(NSDate *)gmtDate
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm"; // drops the seconds

    dateFormatter.timeZone = [NSTimeZone systemTimeZone]; // the local TZ
    NSString *localTimeStamp = [dateFormatter stringFromDate:[NSDate date]];
    // localTimeStamp is the current clock time in the current TZ

    // adjust date so it'll be the same clock time in GMT
    dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    NSDate *gmtDate = [dateFormatter dateFromString:localTimeStamp];
    return gmtDate;
}
  1. В didFinishLaunchingWithOptions: добавьте [NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]], чтобы все средства форматирования даты по умолчанию создавали строки даты в GMT (но никогда не включали часовой пояс в строку формата).

  2. Когда необходимо сохранить дату / время действия пользователя, получите дату через [NSDate gmtDate] и сохраните это значение в своей базе данных.

07.03.2015

2

Запишите часовой пояс вместе с отметкой времени. Используйте этот часовой пояс при форматировании отметки времени позже. Вам нужно будет добавить еще один столбец в таблицу базы данных.

30.01.2015
  • Да, я считаю, что это сработает. Просто кажется, что должен быть способ сделать это исключительно с помощью методов часового пояса (например, установка часового пояса по умолчанию). Может быть нет. Я удивлен, что не видел, чтобы этот вопрос обсуждался в другом месте. 31.01.2015
  • @Jeff - Большинство людей хотят избегать того, что вы пытаетесь сделать. 01.02.2015
  • @Hot Licks - Избегать изменений TZ после входа должно быть обычным делом. Возьмите любое приложение-календарь. За неделю до поездки из США в Австралию я заранее записываюсь на несколько приемов. Например, я ввожу обед в 12:00 в день следующей недели. Когда я приезжаю в Австралию (и устанавливаю свой iPad на австралийское время), мне и всем остальным нужно, чтобы на этой встрече был полдень, а не шесть часов и другой день. В своем приложении я записываю события по мере их возникновения в местном часовом поясе. Позже, когда мой пользователь смотрит на эти события (в другом часовом поясе), он не хочет, чтобы они преобразовывались в какое-то странное время. 03.02.2015

  • 3

    Либо сохраните часовой пояс, как предложил Роб, либо время как NSDate и строку. Используйте строку для пользовательского интерфейса и NSDate для вычислений.

    Или, эй, сделай все три, если они тебе нужны.

    02.02.2015
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]