Rails: как создать объект Time в определенном часовом поясе

Мое приложение работает в часовом поясе "Москва" (+04:00). Но иногда мне нужно создать объект времени только по местному времени (например, "01 мая 2012 13:45") и имени объекта ActiveSupport::TimeZone (например, "Берлин": +02:00 по летнему времени и +01: 00 иначе).

Например, если я получаю "01 мая 2012 13:45" и "Берлин" в качестве входных данных, я хочу получить "2012-05-01 13:45:00 +0200" или "2012-05-01 11:45:00 + 0000". Я создаю следующую функцию:

def from_local_datetime(local_datetime, time_zone)
  offset = Time.now.in_time_zone(time_zone).formatted_offset
  datetime = case local_datetime
  when String
    DateTime.parse(local_datetime)
  else
    DateTime.new(local_datetime)
  end.change(:offset => offset)

  return datetime
end

И на первый взгляд он работает так, как я ожидал. Но является ли это лучшей практикой для такого рода задач? Может быть в какой-то ситуации работает с ошибками. Я не уверен.

Буду рад любым комментариям.

UPD: я думаю, что может возникнуть ошибка, связанная со временем, когда летнее время меняется. Например, 26 марта 2011 г. было GMT+1 в часовом поясе Берлина, а Time.now.in_time_zone("Berlin").formatted_offset возвращает "GMT+1", но 27 марта 2011 г. будет GMT+2. Поэтому, если я позвоню from_local_datetime("28 march 2011", "Berlin") до 27 марта, он вернет 28 march 2011 00:00:00 +0100, но если я позвоню после изменения времени моя функция возвращает 28 march 2011 00:00:00 +0200 :(


person petRUShka    schedule 04.05.2012    source источник
comment
Я не понимаю баг. Берлин в стандартное время (зимой) — UTC/(GMT) +1. То есть, когда в Гринвиче/Париже полдень, в Берлине уже 13:00. Летом берлинцы переводят свои часы на опережение стандартного времени, поэтому, когда полдень по UTC или среднему времени по Гринвичу, в Берлине 14:00.   -  person Marlin Pierce    schedule 04.05.2012
comment
как вы можете видеть из кода выше, я получаю текущее смещение в часовом поясе Берлина с помощью этого кода: Time.now.in_time_zone(time_zone).formatted_offset (+1, если Time.now равно 27 march 2011). Но мне нужен зачет в Берлине, когда будет 28 march 2011 (зачет будет +2).   -  person petRUShka    schedule 05.05.2012


Ответы (2)


Ваш метод преобразования является правильным подходом.

При работе с веб-сайтами вы должны убедиться, что время хранится в базе данных в формате UTC. Если вы можете получить значение UTC из базы данных вместо местного времени (или, может быть, вы можете установить часовой пояс вашего веб-сервера на UTC), ему не нужно будет преобразовывать время из UTC в местное время, когда вы собираетесь чтобы затем все равно преобразовать его в часовой пояс пользователя.

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

person Marlin Pierce    schedule 04.05.2012
comment
Пожалуйста, смотрите ОБНОВЛЕНИЕ в исходном вопросе - person petRUShka; 04.05.2012

TZInfo::Timezone.get('Europe/London')

Найдите часовой пояс

http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html
person Rahul Sharma    schedule 21.02.2017