【问题标题】:How to display the time in user's timezone如何在用户的时区显示时间
【发布时间】:2011-03-10 23:25:33
【问题描述】:

我使用的是 rails 3.0.5,并且我已经以 UTC 格式存储了 created_at 和 updated_at。现在我想在用户的时区显示 created_at 时间。我相信可以从浏览器中选择用户的时区,然后将时间转换为用户的时区。

我确信 rails 会有一个 gem/plugin 来处理这样的事情。有什么事吗?

【问题讨论】:

标签: ruby-on-rails


【解决方案1】:

Rails 默认将每个日期转换为 UTC,然后再将值存储到数据库中。这意味着,无论服务器时区如何,您的数据库中始终有 UTC 日期。

为了将日期转换为用户的时区,您基本上有两种可能性:

  1. 服务器端方法
  2. 客户端方法

服务器端方法

如果您的网站允许注册,您可以将用户时区存储为用户偏好。在用户表中,存储用户时区。然后创建一个自定义助手,您可以使用 in_time_zone 方法将任何日期/时间格式化为正确的时区。

> t = Time.current
# => Mon, 23 Dec 2013 18:25:55 UTC +00:00 
> t.zone
# => "UTC" 
> t.in_time_zone("CET")
# => Mon, 23 Dec 2013 19:25:55 CET +01:00 

你的助手可能看起来像

def format_time(time, timezone)
  time.in_time_zone(timezone)
end

我通常也喜欢使用 I18n.l 帮助器输出标准格式

def format_time(time, timezone)
  I18n.l time.to_time.in_time_zone(timezone), format: :long
end

客户端方法

如果您的网站没有注册,或者您不想向用户询问他们的时区,或者您只是想使用用户系统时区,那么您可以使用 JavaScript。

我的建议是创建一个自定义帮助程序,每次都以适当的方式打印出来,以便您可以创建一个通用的 JavaScript 函数来转换值。

def format_time(time, timezone)
  time = time.to_time
  content_tag(:span, I18n.l(time, format: :long), data: { timezone: timezone, time: time.iso8601 })
end

现在,创建一个在 DOM 加载时执行的 JavaScript 函数,它将选择所有具有 data-time 属性的 HTML 标记。循环它们并使用给定时区中的适当时间更新span 标记内的值。

一个简单的 jQuery 示例是

$(function() {
    $("span[data-time]").each(function() {
        // get the value from data-time and format according to data-timezone
        // write the content back into the span tag
    });
});

我不会在这里发布完整的代码,因为有很多 JavaScript 时间格式化程序可以通过简单的搜索获得。以下是一些可能的解决方案

【讨论】:

  • 抱歉,OP 没有将任何答案标记为正确答案;你的解释了一切,所以它值得奖励:/所以(加上赞成......)谢谢你
  • 这个答案看起来很适合我的应用程序,但我如何将更新后的 Javascript 时间附加到每个网络请求以读取控制器中的时区?
【解决方案2】:

Basecamp 有一个不错的 gem,叫做 local_time 用于客户端渲染 - https://github.com/basecamp/local_time。它非常适合用户未登录且缓存友好的应用程序。

【讨论】:

  • 请注意这个 gem 不支持 i18n
  • 他们于 2017 年 8 月在 2.0.0 版本中添加了 I18n 支持
  • 非常完美,它解决了 95% 的用例。谢谢分享!
【解决方案3】:

您可以将其添加到您的应用程序控制器中,以将所有时间转换为用户的时区:

class ApplicationController < ActionController::Base

  around_filter :user_time_zone, :if => :current_user
  def user_time_zone(&block)
    Time.use_zone(current_user.timezone_name, &block)
  end
end

您只需要捕获用户的时区

【讨论】:

  • 非常感谢!如果要使用服务器时区,只需将current_user.timezone_name 更改为Rails.application.config.time_zone
【解决方案4】:

假设您要显示的值来自数据库,:ie started_at 并且(默认情况下)以 UTC 格式存储。

如果您将用户的时区作为偏移量,您还可以通过以下方式本地化时间:

started_at.in_time_zone(-2)
=> Mon, 24 Feb 2014 23:07:56 GST -02:00

然后可以通过各种方式获得您想要的零件:

started_at.in_time_zone(-2).yesterday
=> Sun, 23 Feb 2014 23:07:56 GST -02:00

started_at.in_time_zone(-2) + 3.days
=> Thu, 27 Feb 2014 23:07:56 GST -02:00

【讨论】:

    【解决方案5】:

    http://api.rubyonrails.org/classes/Time.html#method-c-use_zone

    这就是你要找的:

    Time.use_zone(@user.timezone) do
      blah blah blah
    end
    

    【讨论】:

    • 您需要允许您的用户选择他们的时区。我想你可以“嗅出”这些东西,但最好只是问他们,因为人们很多时候管理来自其他时区的资产,然后是他们所居住的时区。所以@user 是你的用户,而时区是您让他们在他们的个人资料中更新的属性。然后使用use_zone 方法来实例化该区域。或者,您可以只更新您的环境以保存所有时区:local
    • 问题的措辞不同。强制用户填写每个人都可以从教科书中填写的表格。
    【解决方案6】:

    如果您想将日期转换为特定时区:

    deadline.in_time_zone(time_zone)
    

    这里的截止日期是一个日期。

    此外,您可以通过本地机器时区加上本地时间来查找世界时,反之亦然,例如在卡拉奇 - +05:00,您可以简单地将其添加到世界时的值中以查找您所在时区的时间或通过从您的本地时间减去时区差异(在我们的例子中为 05:00)从您的本地时间获取世界时

    【讨论】:

      【解决方案7】:

      我的 jquery 生锈了,所以我花了一点时间才弄清楚如何实现上面接受的答案的客户端方法。

      这是我的解决方案:

      HTML:

      <span data-time="<%= last_message_at %>">&nbsp;</span>
      

      jQuery/Javascript:

      <script type="text/javascript">
      $(document).ready($(function() {
          $("span[data-time]").each(function() {
              var timestamp = $(this).attr("data-time");
              var localeTimestamp = new Date(timestamp).toLocaleString();
              $(this).html(localeTimestamp);
          });
      }));
      </script>
      

      【讨论】:

        【解决方案8】:

        除了 Ben 发布的链接之外,您可能还想看看这些链接:

        【讨论】:

          猜你喜欢
          • 2011-01-18
          • 2018-01-14
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 2010-12-22
          • 2013-02-15
          • 2020-04-15
          相关资源
          最近更新 更多