【问题标题】:Set current Time.zone in Rails?在 Rails 中设置当前 Time.zone?
【发布时间】:2010-10-30 21:00:18
【问题描述】:

我页面上的 Javascript 将客户端 UTC 偏移量保存到 cookie。 如何使用此 cookie 创建 TimeZone 并将其分配给 Time.zone ?

我需要类似的东西:

before_filter :set_time_zone

def set_time_zone
  Time.zone = ActiveSupport::TimeZone.new('my timezone', cookies[:timezone])
end

除了这个表达式的正确部分不起作用,我不确定我在这里是否走对了路。收不到。

【问题讨论】:

  • 请注意Time.zone = 将在全球范围内设置时区(不仅针对此请求);您应该坚持Time.use_zone 并传递一个块以确保该区域仅影响此请求。这适用于 rails 的 around_action 而不是 before_action。

标签: ruby-on-rails timezone


【解决方案1】:

当我将它存储在我的用户模型中时,它就这么简单

def set_time_zone
  Time.zone = current_user.time_zone unless current_user.blank?
end

也许你可以这样做

def set_time_zone
  Time.zone = cookies[:timezone]
end

这是未经测试的,我从未尝试从 cookie 中执行此操作,我认为将其存储在 User 模型中更有意义。

【讨论】:

  • 不,我不需要将它存储在用户模型中。无论如何,您的 current_user.time_zone 是什么样的?是字符串吗?
  • 是的,只是使用 Rails 内置的时区内容,所以对于我的应用中的用户来说,它只是“悉尼”
  • 一般来说,在 Model(MVC 的 M 部分)中访问 session 和 cookie 等对象并不是一个好习惯
  • 如我所见,您在 applicaton_controller.rb 中使用 set_time_zone 方法作为 before_filter 但这是为应用程序设置时区的错误方法,因为 Time.zone 是全局对象,而 zone 是全局属性。你需要像这样使用 around_filter: def set_time_zone old_time_zone = Time.zone if current_user Time.zone = current_administrator.time_zone end yield ensure Time.zone = old_time_zone end
【解决方案2】:

这是有效的谷歌答案:

min = cookies[:timezone].to_i
Time.zone = ActiveSupport::TimeZone[-min.minutes]

为了清楚起见,javascript部分:

if(!($.cookie('timezone'))) {
  current_time = new Date();
  $.cookie('timezone', current_time.getTimezoneOffset(), { path: '/', expires: 10 } );
} 

【讨论】:

  • 您可能还需要删除 >>> if(!($.cookie('timezone')))
  • 一个小问题:TimeZone[-min.minutes] 返回第一个可用时区,偏移量为min.minutes。例如,对于东京,它返回伊尔库茨克。因此,如果您不需要显示时区名称或代码,此方法将起作用。
  • @arkadiy 是对的,但这不仅仅是一个小问题,因为您可以获得不遵守夏令时 (DST) 的时区。在这种情况下,结果是错误的时间。此外,new Date().getTimezoneOffset() 返回包括 DST 在内的当前偏移量,但 ActiveSupport::TimeZone[] 选择需要标准时区偏移量,因此您应该更新您的 JavaScript 函数 like this。如果您想了解更多信息,可以查看this thread 了解该问题。
【解决方案3】:

@snitko - 你的回答对我来说很长一段时间都很好。但是,正如@Giovanni 指出的那样,它在某些情况下没有考虑夏令时,因为它在给定分钟偏移量的情况下提取了第一个可用的时区。我找到了一个解释 DST 的简单有效答案。

到这里 - http://site.pageloom.com/automatic-timezone-detection-with-javascript,它是一个 javascript 时区检测器。您只需将从网站链接的 javascript 代码(或正确的 here)复制到您的应用程序的一个 javascript 文件中(application.js 工作正常)。它允许您通过名为jstz 的对象检索时区。

然后,在 application.html.erb 我有

<script type="text/javascript">

  var timezone = jstz.determine();
  document.cookie = 'time_zone='+timezone.name()+';';

</script>

在 application_controller.rb 中,我有

before_filter :set_timezone 

private
def set_timezone
  Time.zone = cookies["time_zone"]
end

这就是你所需要的!为您的 Rails 应用正确设置了时区。

编辑:由于加载 javascript 文件的方式和顺序不同,您可能需要将 javascript cookie 设置代码放在 application.html.erb 中的 &lt;\body&gt; 标记之后。

【讨论】:

  • 嘿,我知道它很长一段时间.. 但我正在这样做。你能澄清最后一行吗?而且设置cookie后是否不用刷新页面,影响当前页面?
  • 最后一行将时区设置为应用程序的全局配置。如果您有很多人从不同的时区访问您的应用程序,这可能不是最好的方法(与为单个用户设置时区相比)。但是是的,您是正确的,您需要刷新页面,以便服务器使用更新的时区呈现页面,以查看任何与时间相关的更改。
  • 嘿,我相信 Time.zone 是线程安全的,只要你在每个请求上都设置它,我不认为应该在请求之间进行干预吧?另外,我实际上是指您的 EDIT: 行,它谈到将 cookie 内容放在最后?
  • 啊。是的,我不记得为什么要添加 EDIT。已经很长时间了,但当时我正在构建一个 Rails 应用程序,我相信我遇到了一个问题,即除非在 &lt;/body&gt; 标记之后,否则代码不会运行。
  • 啊,好吧,不用担心,它在页面顶部为我工作,至少在开发中
猜你喜欢
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多