4

(我在 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?

4

2 回答 2

13

破解它!

基本上,提交给 params 的字符串代表酒店时区的时间。我们必须使用内置的 'use_zone' 方法将全局 Time.zone 临时设置为该酒店的。

然后,我们向该方法传递一个块,在该块中我们使用 Hotel 的时区而不是 User 来生成 Rails 期望的值。这意味着 Rails 转换为 UTC 会在 db 中产生正确的时间 - 因为在表单上输入的时间已转换为用户时区。这些偏移量有效地相互抵消了。

@document.created_at = Time.use_zone(@current_hotel.timezone) {Time.zone.parse("#{params[:document][:created_at]}").in_time_zone(@current_hotel.timezone)}

我们基本上是在这里更改 Time 对象的时区,而不会在时区更改时转换该 Time 对象的实际时间。(祝你好运解析那句话!)

这看起来对我来说很好,但是我已经研究这个太久了,我很想看到一个更好的方法/更多的 Rails-ey 方法来做到这一点!

于 2012-04-06T09:23:59.970 回答
2

datetime类型仅存储日期和时间,但不存储时区。您可能需要创建一个辅助列来保留用于解释保存在那里的 UTC 时间的时区。

这两个值可以结合起来重新创建您的初始输入。

于 2012-04-05T14:52:31.397 回答