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