Подтвердить что ты не робот

Как преобразовать идентификатор 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 %>
4b9b3361

Ответ 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, очевидно, пересматривает поддержку часовых поясов, чтобы очистить этот бизнес