Перетворення часу з одного часового поясу в інший в Rails


105

Мої created_atчасові позначки зберігаються в UTC:

>> Annotation.last.created_at
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00

Як перетворити одну з них на "Східний час (США та Канада)" (з урахуванням економії денного світла)? Щось на зразок:

Annotation.last.created_at.in_eastern_time

Відповіді:


191

Використовуйте метод in_time_zone класу DateTime

Loading development environment (Rails 2.3.2)
>> now = DateTime.now.utc
=> Sun, 06 Sep 2009 22:27:45 +0000
>> now.in_time_zone('Eastern Time (US & Canada)')
=> Sun, 06 Sep 2009 18:27:45 EDT -04:00
>> quit

Тож для вашого конкретного прикладу

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')

7
або ви можете просто використовувати годинний ідентифікаторnow.in_time_zone(3)
fl00r

8
created_at.in_time_zone("EST")коротше
Орландо

51
"EST" = "Східний стандартний час", тому це буде неправильно під час літнього часу. "Східний час (США та Канада)" визначає, чи це для вас DST чи ні.
jhiro009

1
Зауважте, що метод in_time_zone є частиною ActiveSupport, тому він вбудований у Rails, але не є частиною stdlib Ruby. Якщо у вас є програма для рейок, немає проблем. Якщо у вас є прямий додаток Ruby, вам потрібно буде обов’язково вимагати активної підтримки.
Гейл

Посилання на документацію для цього методу знаходиться тут: apidock.com/rails/DateTime/in_time_zone
Khan

17

Хоча це старе питання, варто щось згадати. У попередній відповіді пропонується скористатися pre_filter, щоб тимчасово встановити часовий пояс.

Ви ніколи не повинні цього робити, тому що Time.zone зберігає інформацію в потоці, і вона, ймовірно, просочиться до наступного запиту, обробленого цим потоком.

Натомість слід скористатися навколо_фільтром, щоб переконатися, що Time.zone скидається після завершення запиту. Щось на зразок:

around_filter :set_time_zone

private

def set_time_zone
  old_time_zone = Time.zone
  Time.zone = current_user.time_zone if logged_in?
  yield
ensure
  Time.zone = old_time_zone
end

Детальніше про це читайте тут


1
В даний час є приємний метод Time.use_zone .
freemanoid

9

Якщо ви додасте це до свого /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

Тоді ви можете осередок

Annotation.last.created_at.in_time_zone

щоб отримати час у вказаному часовому поясі.


якщо ми налаштовуємо часовий пояс у application.rb, тоді не потрібно викликати ".in_time_zone". рейки автоматично роблять це для нас, якщо вам потрібно викликати Annotation.last.create_at
Vishal

3

Якщо ви налаштуєте свій /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

Time.now.in_time_zone

DateTime.now.in_time_zone

2

Встановіть свій часовий пояс на східний час.

Ви можете встановити часовий пояс за замовчуванням у config / environment.rb

config.time_zone = "Eastern Time (US & Canada)"

Тепер усі записи, які ви витягуєте, будуть знаходитися в тому часовому поясі. Якщо вам потрібні різні часові пояси, скажімо, на основі часового поясу користувача, ви можете змінити його за допомогою попереднього фільтра у вашому контролері.

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

Просто переконайтеся, що ви весь час зберігаєте в базі даних як UTC, і все буде приємно.


Це має значення, якщо ви використовуєте сервер додатків, наприклад, монгрел, тонкий або пасажирський? Вони працюють більше ніж один екземпляр, я вважаю, одна нитка? Я можу помилятися, хотів би знати!
nitecoder


Можливо, це не було у09 році?
nitecoder

2
@jpwynn: відповідно до цього: github.com/rails/rails/commit/… Нитка безпечна вже більше 5 років. Будь-яке джерело чи приклад вашої проблеми?
Паскаль

1
Нитка може обслуговувати кілька сеансів. Якщо ви встановите його один раз, коли користувач увійде в систему, наприклад, ОСТАННІЙ користувач для входу, встановить часовий пояс для ВСІХ користувачів, сеанс яких використовує ту саму нитку. Таким чином, Ви ОБОВ'ЯЗКОВО використовувати передустановку, щоб встановити її для кожного користувача при кожному завантаженні сторінки.
jpw
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.