Мы создаем приложение rails, которое должно отображать даты (и, что более важно, рассчитывать их) в нескольких часовых поясах.
Может кто-нибудь подсказать мне, как работать с пользовательскими часовыми поясами в rails 2.3 (.5или .8)
Самая содержательная статья, которую я видел, подробно рассказывающая о том, как пользовательские часовые пояса должны работать, находится здесь: http://wiki.rubyonrails.org/howtos/time-zones..., хотя неясно, когда это было написано или для какой версии рельсов,В частности, в нем говорится:
"Time.zone - часовой пояс, который фактически используется для отображения. Он может быть установлен вручную для переопределения config.time_zone для каждого запроса."
Используются ключевые термины «цели отображения» и «на основе запроса».
Локально на моей машине это действительно так.Однако на производстве, ни один из них не соответствует действительности.Настройка Time.zone сохраняется после окончания запроса (ко всем последующим запросам), а также влияет на способ сохранения AR в БД (в основном обрабатывая любую дату, как если бы она уже была в UTC, даже если ее нет), сохраняя тем самым совершенно неподходящие значения.
Мы запускаем Ruby Enterprise Edition на производстве вместе с пассажирами.Если это моя проблема, нам нужно переключиться на JRuby или что-то еще?
Чтобы проиллюстрировать проблему, я поместил следующие действия в мой ApplicationController прямо сейчас:
def test
p_time = Time.now.utc
s_time = Time.utc(p_time.year, p_time.month, p_time.day, p_time.hour)
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
logger.error p_time.inspect
logger.error s_time.inspect
jl = JunkLead.create!
jl.date_at = s_time
logger.error s_time.inspect
logger.error jl.date_at.inspect
jl.save!
logger.error s_time.inspect
logger.error jl.date_at.inspect
render :nothing => true, :status => 200
end
def test2
Time.zone = 'Mountain Time (US & Canada)'
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
render :nothing => true, :status => 200
end
def test3
Time.zone = 'UTC'
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
render :nothing => true, :status => 200
end
и они даютследующее:
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:50) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Fri Dec 24 22:15:50 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Completed in 21ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
Processing ApplicationController#test2 (for 98.202.196.203 at 2010-12-24 22:15:53) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200>
nil
Completed in 143ms (View: 1, DB: 3) | 200 OK [http://www.dealsthatmatter.com/test2]
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:59) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200>
nil
Fri Dec 24 22:15:59 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 15:00:00 MST -07:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 15:00:00 MST -07:00
Completed in 20ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
Processing ApplicationController#test3 (for 98.202.196.203 at 2010-12-24 22:16:03) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Completed in 17ms (View: 0, DB: 2) | 200 OK [http://www.dealsthatmatter.com/test3]
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:16:04) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Fri Dec 24 22:16:05 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Completed in 151ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
Выше должно быть ясно, что второй вызов / test показывает, что для Time.zone установлено значение Mountain, хотя это не должно быть.
Кроме того,проверка базы данных показывает, что действие test при запуске после test2 сохранило запись JunkLead с датой 2010-12-22 15:00:00, что явно неверно.