Как преобразовать идентификатор TZInfo в Rails TimeZone name/key
Как преобразовать значения js, полученные как идентификаторы TZInfo, в Rails TimeZone name/key?
FROM: "America/New_York"
, возвращенный из определения TZinfo JavaScript
TO: "Eastern Time (US & Canada)"
соглашение, используемое в Rails TimeZone
или другой пример:
"Pacific/Honolulu"
= > преобразован в = > "Hawaii"
Оба доступны в формате ActiveSupport::TimeZone < Object
, но рельсы используют ключ [i.g. "Eastern Time (US & Canada)"
] в раскрывающихся списках, проверка и сохранение до Time.use_zone()
.
Основываясь на том, что я понимаю в ActiveSupport::TimeZone.us_zones
, это, по-видимому, важно, особенно в случае сбережения времени DayLights (которые рельсы звучат хорошо для обработки), и совпадение только смещения не будет достигнуто. Если он не хранится в БД с именем TimeZone рельсов, то проверка не выполняется и не соответствует правильной странице настроек профиля пользователя с выпадающим списком ActiveSupport::TimeZone.zones_map
Цель состоит в том, что пользователю не нужно выбирать свой часовой пояс при регистрации или требуется изменить его в своих настройках после регистрации. Браузер обнаруживает его и передает его в hidden_field при регистрации. В редких случаях они регистрируются в месте, отличном от дома/работы. они могут вручную переопределить в своих настройках учетной записи позже.
Кажется, что это общий пробел при попытке проникновения js-часового пояса. Это может даже стать второстепенным вопросом о том, как передать возвращаемую информацию из js в rails для преобразования, а затем вернуться в js для сохранения обратно в скрытом поле формы? Надеюсь, я правильно сформулировал вопрос и, по общему признанию, немного зеленый с рельсами, поэтому может быть простое решение для этого...
Большое спасибо за помощь!
-E
Документация ActiveSupport Time.zone
http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse
MAPPING = {"Eastern Time (US & Canada)" => "America/New_York"
Использование js packaged gem 'temporal-rails' для обнаружения часового пояса пользователей:
https://github.com/jejacks0n/temporal
Пользователь Time_Zone реализует как видно:
http://railscasts.com/episodes/106-time-zones-revised
* Использование Devise и Devise-Inevitable
Вид регистрации Script
<script>
$(function() {
var detected_zone = Temporal.detect();
console.log(detected_zone); // returns object
detected_zone = detected_zone.timezone.name;
console.log(detected_zone); // returns "America/New_York"
$('#user_time_zone').val(detected_zone); // ! need to convert this to rails TimeZone name !
});
</script>
Модель пользователя
validates_inclusion_of :time_zone, in: ActiveSupport::TimeZone.zones_map(&:name)
Форма настроек учетной записи пользователя
<%= f.label :time_zone, label: "Time Zone" %><br />
<%= f.time_zone_select :time_zone, ActiveSupport::TimeZone.us_zones %>
Ответы
Ответ 1
Temporal включает в себя необходимую логику, но чтобы ответить на ваш вопрос:
Time.zone = ActiveSupport::TimeZone.new("America/New_York")
Редактировать, я думаю, мой ответ неполон. Вы хотите перевести это из "Америка/Нью-Йорк" в "Восточное время (США и Канада)", верно? Если это так, то это лучшее решение, которое у меня есть, хотя кто-то может предложить лучшее.
ActiveSupport::TimeZone::MAPPING.select {|k, v| v == "America/New_York" }.keys.first
Ответ 2
Волшебство, которое, я полагаю, всем действительно нужно, и решает проблему, поднятую @ajbraus, - это одна строчка, которая может оказаться одной из самых странных вещей, которые можно найти в любом месте:
timezone = ActiveSupport::TimeZone[TZInfo::Timezone.get('America/Vancouver').period_for_utc(Time.now.utc).utc_offset]
=> #<ActiveSupport::TimeZone:0x00007fc2baa6d900 @name="Pacific Time (US & Canada)", @utc_offset=nil, @tzinfo=#<TZInfo::TimezoneProxy: America/Los_Angeles>>
В противном случае, если вы попытаетесь выполнить поиск по всей базе данных ActiveSupport, вы получите nada:
ActiveSupport::TimeZone.all.find{ |tz| tz.tzinfo == ActiveSupport::TimeZone.find_tzinfo('America/Vancouver') }
=> nil
Сложность сводится к следующему:
- TZInfo Gem строго придерживается спецификации часовых поясов IANA
- ActiveSupport от Rails решил попробовать и упростить отображение/использование зон, но не является исчерпывающей базой данных зон
- ActiveSupport может искать соответствующую зону, если вы даете ей смещение
- TZInfo не дает вам смещения, если вы не создадите TZInfo :: TimezonePeriod в интересующей зоне
- Ruby 2.6, очевидно, пересматривает поддержку часовых поясов, чтобы очистить этот бизнес