Time.now против Time.zone.now в Rails
June 4, 2010 in Ruby on RailsФункции Time.now
и Time.zone.now
в Ruby on Rails практически идентичны. Возвращают одни и те же значения, ведут себя одинаково. Из-за этого легко перепутать и использовать более короткую формулировку Time.now
. А зря – по крайней мере, если ты используешь часовой пояс, отличный от UTC.
В чем же разница между этими функциями? А вот в чем:
>> Time.now.class => Time >> Time.now.to_s :db => "2010-06-04 19:00:00" >> Time.zone.now.class => ActiveSupport::TimeWithZone >> Time.zone.now.to_s :db => "2010-06-04 16:00:11"
Дело в том, что Rails, начиная с версии 2.1, хранят время в базе в UTC, а при сохранении и чтении переводят его из и в часовой пояс, используемый в приложении.
За перевод времени в UTC отвечает, как ни странно, метод to_s(:db)
. Точнее странно то, что, хоть он и доступен у объекта типа Time
, работает он неверно и отдает время в текущем часовом поясе. Если использовать Time.now
в условиях запроса – они сместятся на определенное количество часов. Если записывать Time.now
в базу – в базу запишется неправильное значение, потому что при чтении рельсы лишний раз добавят к нему смещение часового пояса.
Короче, наиболее простым и адекватным решением этой проблемы будет замена по всему проекту Time.now
на Time.zone.now
.
…А еще из-за это проблемы не стоит использовать в запросах функцию MySQL NOW()
и аналогичные, поскольку они ничего не знают о настройках рельсов.
Понравился пост? Купи мне кофе