【问题标题】:How to present Rails form datetime select in different time zone?如何在不同时区呈现 Rails 表单日期时间选择?
【发布时间】:2013-08-24 12:20:33
【问题描述】:

我想在用户的首选时区中向用户显示日期时间选择,但将日期时间存储为 UTC。目前,默认行为是使用 UTC 显示和存储日期时间字段。如何在不影响整个应用程序的情况下更改此字段的行为(即不更改应用程序默认时区)?

更新:这不是每个用户的时区。我不需要调整时间的显示方式。只有这些特定字段处理不同的时区,所以我希望用户能够指定该时区的时间。

【问题讨论】:

  • 您是否尝试过使用ActiveSupport::TimeZoneTZInfo gem?或者您正在寻找客户端 JavaScript 解决方案?也许显示一些代码? :)
  • 不,不是客户端。是的,在显示特定区域的时间时,我已经使用标准时区助手,即Time.now.in_time_zone("Pacific Time (US & Canada)")。但是,现在我需要更改表单显示相对于给定时区的值的方式。

标签: ruby-on-rails ruby forms datetime timezone


【解决方案1】:

以下是允许用户使用特定时区设置日期的方法:

要将表单中提交的多参数属性转换为特定时区,请在控制器中添加一个方法以手动将参数转换为日期时间对象。我选择将此添加到控制器中,因为我不想影响模型行为。您应该仍然可以在模型上设置日期并假设您的日期设置正确。

def create
  convert_datetimes_to_pdt("start_date")
  convert_datetimes_to_pdt("end_date")
  @model = MyModel.new(params[:my_model])
  # ...
end

def update
  convert_datetimes_to_pdt("start_date")
  convert_datetimes_to_pdt("end_date")
  # ...
end

def convert_datetimes_to_pdt(field)
  datetime = (1..5).collect {|num| params['my_model'].delete "#{field}(#{num}i)" }
  if datetime[0] and datetime[1] and datetime[2] # only if a date has been set
    params['my_model'][field] = Time.find_zone!("Pacific Time (US & Canada)").local(*datetime.map(&:to_i))
  end
end

现在日期时间将调整为正确的时区。但是,当用户去编辑时间时,表单字段仍会以 UTC 显示时间。为了解决这个问题,我们可以将字段包装在对 Time.use_zone 的调用中:

Time.use_zone("Pacific Time (US & Canada)") do
  f.datetime_select :start_date
end

【讨论】:

    【解决方案2】:

    有几个选项:

    • 在向用户显示数据时使用用户的本地时区。使用 browser-timezone-rails gem 之类的东西真的很容易。见https://github.com/kbaum/browser-timezone-rails。它本质上是根据从浏览器检测到的时区覆盖每个请求的应用程序时区。注意:它仅使用操作系统时区,因此不如基于 IP/地理位置的解决方案准确。
    • 设置您的应用程序时区,使其与您的大多数用户群保持一致。例如:config.time_zone = 'Mountain Time (US & Canada)'。这是在rails中做的非常标准的事情。 Rails 将始终以 UTC 格式将数据存储在数据库中,但会使用应用程序时区显示/加载数据。
    • 为您的用户模型创建一个时区。允许用户在其帐户设置中设置此值。然后,在 application_controller 中使用与上述 gem 类似的方法。

    【讨论】:

    • 感谢您的回答。对不起,我不清楚。这不是每个用户的时区,而是不同于应用程序默认时区的特定时区。我只需要调整表单显示时间选择的方式。它应该显示应用了时区偏移的值。
    • 我认为您需要先将日期时间转换为所需的时区,然后才能在表单中显示。您可以使用 Time.use_zone 的块形式来执行此操作。
    • Time.use_zone('你想使用的时区') do study_at = Time.zone.parse('datetime string') end
    • 好吧,用Time.use_zone 包裹表单字段在编辑表单时有效,现在我只需要弄清楚在保存值时在哪里使用它。
    猜你喜欢
    • 2011-09-08
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 2011-03-04
    相关资源
    最近更新 更多