Как получить time_zone_options_for_select со смещением летнего времени?

ActionView::Helpers::FormOptionsHelper предоставляет time_zone_options_for_select для получения списка параметров. для элемента управления select, который включает все часовые пояса с их смещением UTC. Проблема, с которой я столкнулся, заключается в том, как заставить его отображать правильное смещение, когда действует летнее время?

Например, горное время США обычно составляет -7 UTC, но летом оно эффективно -6 UTC. Есть ли способ, чтобы этот список правильно отражал это?


person Beardo    schedule 09.06.2011    source источник
comment
@stevec - Не знаю, почему вы разместили здесь вознаграждение вместо того, чтобы задать вопрос, но также, пожалуйста, прокрутите вниз до тега часового пояса и прочитайте раздел о часовых поясах Rails. Спасибо.   -  person Matt Johnson-Pint    schedule 04.01.2021
comment
@stevec - я добавил ответ, который, как мне кажется, достаточно отвечает на ваш вопрос.   -  person taylorthurlow    schedule 07.01.2021


Ответы (2)


У меня была аналогичная проблема, но в итоге я использовал это

time_zone_select('time_zone', TZInfo::Timezone.us_zones, 
                                     :default => "America/Los_Angeles", 
                                     :model => TZInfo::Timezone

Вы нашли лучшее решение?

person aliibrahim    schedule 25.05.2012

TL;DR

Полученные вами данные о часовом поясе верны, поскольку экземпляры ActiveSupport::TimeZone и TZInfo::Timezone не делают предположений о текущей дате, и поэтому применение к ним летнего времени не имеет смысла в контексте ответственности этих объектов.

Вы замечаете проблему, потому что модель по умолчанию для time_zone_options_for_select, ActiveSupport::TimeZone, к сожалению, возвращает строку смещения при вызове #to_s, которая, если местоположение в настоящее время соблюдает летнее время, будет неверным. Невозможно исправить строковые значения, сгенерированные в опциях, или даже удалить из них смещение.

Если это неприемлемо, вам нужно пропустить использование time_zone_options_for_select и использовать options_for_select и создайте параметры самостоятельно.

Некоторое расследование

time_zone_options_for_select использует ::ActiveSupport::TimeZone в качестве параметра model по умолчанию, поэтому передача его вручную не изменит ваши результаты. Чтобы создать параметры для поля выбора, этот метод создаст массив кортежей в формате [time_zone.to_s, time_zone.name] для передачи его более общему методу options_for_select. time_zone в данном случае является экземпляром ::ActiveSupport::TimeZone.

Важным фактором здесь является то, что этот объект экземпляра часового пояса концептуально совершенно не связан/отделен от идеи текущей даты. Определение часового пояса (строго говоря) не имеет ничего общего с текущей датой. Мы можем подтвердить это, не используя проблему перехода на летнее время следующим образом:

::ActiveSupport::TimeZone.all.find { |tz| tz.name == "Adelaide" }.utc_offset
=> 34200 # 9 hours and 30 minutes, in seconds

Часовой пояс Аделаиды без перехода на летнее время - это ACST (центральное стандартное время Австралии), который составляет GMT + 9,5. В настоящее время (как и на момент написания) в Аделаиде летнее время, что означает, что они находятся на ACDT (центральное летнее время Австралии), то есть по Гринвичу + 10,5.

::ActiveSupport::TimeZone.all.find { |tz| tz.name == "Adelaide" }.now.utc_offset
=> 37800 # 10 hours and 30 minutes, in seconds

Важным отличием здесь является то, что я обрисовал выше: экземпляр ActiveSupport::TimeZone просто не связан с текущей датой. Сам класс представляет собой удобную оболочку для экземпляра TZInfo::DataTimezone, который имеет аналогичные мнения на текущую дату — нет.

Если вы заметили, во втором фрагменте кода выше мы вызвали #now для объекта часового пояса перед вызовом #utc_offset. Это возвращает экземпляр ActiveSupport::TimeWithZone, который включает информацию о часовом поясе, а также текущую дату, и поэтому мы получаем смещение, которое отражает тот факт, что текущая дата должна включать смещение летнего времени.

Таким образом, единственная проблема здесь заключается в том, что включение строки смещения UTC в возвращаемое значение #to_s для экземпляров ActiveSupport::TimeZone в данном случае вводит в заблуждение. Он включен, потому что это базовое смещение UTC для этого часового пояса.

Ресурсы:

person taylorthurlow    schedule 07.01.2021