Помогите гроккингам времени и часовых поясов в Rails 3 - PullRequest
8 голосов
/ 27 июня 2011

Я знаю, что есть несколько десятков подобных вопросов, не говоря уже о бесчисленных статьях о Interwebs в целом, но мне все еще трудно понять, как Rails работает с часовыми поясами внутри.

У меня в данный момент настроено config.time_zone = 'Eastern Time (US & Canada)' в моем файле приложения, потому что там я и другие администраторы проекта. Компания, владеющая сайтом, базируется в CA, поэтому они будут работать по тихоокеанскому времени. Приложение имеет глобальную аудиторию, и хотя мы этого еще не сделали, в конечном итоге мы будем внедрять предпочитаемые пользователем часовые пояса.

Итак, мои текущие вопросы:

  1. Я знаю, что Rails волшебным образом преобразует значения столбца datetime в и из UTC при сохранении и получении соответственно, но как правильно просматривать локальную версию данного атрибута datetime?

  2. Когда можно использовать Time.now против Time.zone.now против Time.now.in_time_zone против DateTime.now против DateTime.now.in_time_zone?

  3. Как правильно сравнить данный атрибут datetime с методами, перечисленными выше, или какое-либо другое конкретное время относительно текущего настроенного часового пояса? С UTC?

  4. У нас будут некоторые чувствительные ко времени вещи, такие как статьи, которые должны быть опубликованы в определенное время в соответствии с часовым поясом приложения, поэтому как мне заставить приложение делать это сравнение в указанном часовом поясе, а не в настоящее время настроен один (при условии, что пользовательские часовые пояса реализованы?)

  5. ( Новый вопрос ) Что произойдет, если я изменю config.time_zone на UTC позднее? Нужно ли сбрасывать все мои времена в базе данных, или это влияет на старое время?

1 Ответ

8 голосов
/ 11 августа 2012

Во-первых, важно понимать, что материал часовых поясов рельсов в основном связан с презентацией. За кулисами все происходит в UTC.

Q1. На консоли Rails будет отображать время в вашем часовом поясе по умолчанию, поэтому Something.last.created_at отображает эту временную метку в зоне, заданной Time.zone

Q2. Все они возвращают объект, который представляет «сейчас». Выбор даты и времени не зависит от часовых поясов. Если вам нужно, например, представлять время за пределами эпохи Unix, используйте DateTime. Разница между Time.now и Time.zone.now заключается в том, получите ли вы обратно экземпляр Time (который будет находиться в локальном часовом поясе сервера в качестве контроллера). Например, это контролирует то, что возвращает to_s, но не то, какой момент времени представлен:

SomeModel.create(:time_attribute => Time.now)
SomeModel.create(:time_attribute => Time.zone.now)

вставит эту же строку в базу данных. Если вы просто отображаете время для пользователя (например, если ваш сайт отображает текущее время в заголовке), вам следует использовать Time.zone.now, чтобы оно отображалось в правильном часовом поясе. Если вы просто храните его в БД, это не имеет значения - activerecord все равно преобразует его в TimeWithZone.

Q3. Методы сравнения в TimeWithZone реализованы путем сравнения версии даты в формате utc, поэтому вы можете безопасно сравнивать время в разных зонах - вам не нужно преобразовывать их в какой-либо общий часовой пояс. Вы также можете сравнивать экземпляры TimeWithZone с обычными объектами времени.

Q4. Обычно вам не нужно ничего делать. Распространенным способом реализации этого является использование атрибута published_at в вашей модели. Страницы, отображающие список статей, добавят

where('published_at <= ?', Time.now)

условие к запросу. Когда вы создаете свою статью, Rails берет дату из формы и преобразует ее в utc, поэтому в базе данных хранится версия utc этого published_at времени. Сравнения не зависят от часового пояса, поэтому запрос работает независимо от часового пояса.

Это может усложниться из-за чистого времени суток (например, «4 часа дня»), потому что преобразование часового пояса может быть выполнено правильно только тогда, когда вы знаете дату (т.е. вы знаете точный момент времени), как в зависимости от летнего времени. (или политические события, такие как страны, меняющие свой часовой пояс) смещение от изменений UTC. В такой ситуации обычно требуется сохранять только время суток и преобразовывать его в полное время как можно позже, если вы знаете дату тоже.

В5. Rails всегда хранит UTC в базе данных. Прямым следствием этого является то, что изменение config.time_zone не требует изменения данных, хранящихся в базе данных. Вы даже можете установить Time.zone для каждого пользователя, чтобы пользователи видели время в своем часовом поясе - config.time_zone просто контролирует значение по умолчанию Time.zone

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...