如何在用户的时区显示时间

时间:2011-03-10 23:25:33

标签: ruby-on-rails

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

我确信rails会有一个gem /插件来处理这样的事情。有东西吗?

8 个答案:

答案 0 :(得分:52)

默认情况下,Rails会在将值存储到数据库之前将每个日期转换为UTC。这意味着,无论服务器时区如何,您的数据库中始终都有UTC日期。

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

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

    如果您的网站允许注册,您可以将用户时区存储为用户首选项。在用户表中,存储用户时区。然后创建一个自定义帮助程序,您可以使用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时间格式器可以通过简单的搜索。这里有一些可能的解决方案

答案 1 :(得分:15)

Basecamp有一个很棒的宝石叫做local_time,用于客户端渲染 - https://github.com/basecamp/local_time。这对于用户未登录且缓存友好的应用程序非常有用。

答案 2 :(得分:5)

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

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

您只需要捕获用户的时区

答案 3 :(得分:3)

假设您想要显示的值来自数据库,例如: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

答案 4 :(得分:1)

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

这就是你要找的东西:

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

答案 5 :(得分:1)

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

deadline.in_time_zone(time_zone)
  

截止日期是一个日期。

此外,您可以通过本地计算机时区加上本地时间来查找世界时间,反之亦然,例如在卡拉奇-+05:00中,您只需将其添加到世界时间中的值即可在您的时区中找到时间,或者通过从您的本地时间中减去时区时差(在我们的示例中为05:00)来从您的本地时间获得世界标准时间

答案 6 :(得分:0)

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

答案 7 :(得分:0)

我的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>