(我在Ruby MRI 1.9.2上使用Rails 3.2.3)
所有内容都以UTC格式存储。这很好。每个用户都有一个'时区'属性。我的ApplicationController有一个前置过滤器,可以将Time.zone调整为用户存储的时区。这也很好。
鉴于上述情况,如果我的用户使用时间完成日期时间选择,那么该时间预计将在Time.zone中,并且Rails将自动调整并将其保存为UTC。这也很好。
现在:我希望我的用户能够在其他时区填写时间 ,然后将其存储为UTC。但是,Rails期望已完成的日期时间选择(在之前由ApplicationController设置)Time.zone中填写。因此,Rails会调整为UTC 错误。
如何实现将输入时间保存为第三时区的目标?
插图:
我的使用场景是佛罗里达州的用户调整属于西海岸酒店的文档的日期。他们希望进入西海岸的时间。
我正在使用jQuery来设置带有样式选取器的文本框,所以我有一个方法将字符串输出到文本框:
<%= f.text_field(:created_at, :value => adjusted_to_hotel_time(@document.created_at), :class => 'text datetime_picker') %>
def adjusted_to_hotel_time(time)
time.in_time_zone(@current_hotel.timezone).to_s(:admin_jquery) # formatted for the jQuery datetime_picker text fields.
end
这很好用,但是当保存@document时,Rails会错误地调整为UTC。我不知道我不知道的是什么 - 如何将在该字段中输入的数据“标记”为@ current_hotel.timezone,以便Rails在保存父对象时将正确地偏移到UTC?
答案 0 :(得分:13)
破解了!
基本上,提交给params的字符串表示酒店时区的时间。我们必须使用内置的'use_zone'方法临时将全局Time.zone设置为该酒店的。
然后,我们通过使用酒店的时区而不是用户,将方法传递给我们生成Rails所期望的值的块。这意味着Rails转换为UTC会导致数据库中的正确时间 - 因为在表单上输入的时间已转换为用户时区。抵消有效地取消了对方。
@document.created_at = Time.use_zone(@current_hotel.timezone) {Time.zone.parse("#{params[:document][:created_at]}").in_time_zone(@current_hotel.timezone)}
我们基本上在这里更改时间对象的时区,而不是在时区变化时转换该时间对象的实际时间。(祝你好运解析那句话! )
这看起来对我来说很好,但是我已经看了很久了,我很想看到更好的方式/更多的Rails-ey这样做的方式!
答案 1 :(得分:2)
datetime
列类型仅存储日期和时间,但不存储时区。您可能需要创建辅助列以保留用于解释其中保存的UTC时间的时区。
这两个值可以组合起来重新创建初始输入。