Ruby-on-rails 如何在用户的时区显示时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5267170/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to display the time in user's timezone
提问by Nick Vanderbilt
I am using rails 3.0.5 and I have created_at and updated_at stored in UTC. Now I want to display the created_at time in users' timezone. I believe it is possible to pick user's timezone from the browser and then convert time to user's timezone.
我正在使用 rails 3.0.5 并且我已经 create_at 和 updated_at 存储在UTC中。现在我想在用户的时区中显示 created_at 时间。我相信可以从浏览器中选择用户的时区,然后将时间转换为用户的时区。
I am sure rails will have a gem/plugin to take care of something like this. Is there something?
我相信 rails 会有一个 gem/plugin 来处理这样的事情。有什么吗?
回答by Simone Carletti
Rails by default converts every date into UTC before storing the value into the database. This means that, regardless the server timezone, you always have UTC dates in your database.
默认情况下,Rails 在将值存储到数据库之前将每个日期转换为 UTC。这意味着,无论服务器时区如何,您的数据库中始终都有 UTC 日期。
In order to convert the dates into your user's timezone you have basically two possibilities:
为了将日期转换为用户的时区,您基本上有两种可能性:
- server-side approach
- client-side approach
- 服务器端方法
- 客户端方法
Server-side approach
服务器端方法
If your site allows registration, you can store the user timezone as user preference. In the user table, store the user timezone. Then create a custom helper you can use to format any date/time into the proper timezone using the in_time_zonemethod.
如果您的站点允许注册,您可以将用户时区存储为用户首选项。在用户表中,存储用户时区。然后创建一个自定义助手,您可以使用该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
Your helper may looks like
你的助手可能看起来像
def format_time(time, timezone)
time.in_time_zone(timezone)
end
I normally also like to output a standard format, using the I18n.lhelper
我通常也喜欢使用I18n.lhelper输出标准格式
def format_time(time, timezone)
I18n.l time.to_time.in_time_zone(timezone), format: :long
end
Client-side approach
客户端方法
If your site has no registration or you don't want to ask your users for their timezone or you simply want to use the user system timezone, then you can use JavaScript.
如果您的站点没有注册,或者您不想询问用户的时区,或者您只想使用用户系统时区,那么您可以使用 JavaScript。
My suggestion is to create a custom helper that will print out every time in a proper way so that you can create a generic JavaScript function to convert the values.
我的建议是创建一个自定义助手,每次都以适当的方式打印出来,以便您可以创建一个通用的 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
Now, create a JavaScript function that is performed on DOM load and that will select all the HTML tags with data-timeattribute. Loop them and update the value inside the spantag with the proper time in the given timezone.
现在,创建一个在 DOM 加载时执行的 JavaScript 函数,它将选择所有具有data-time属性的 HTML 标签。循环它们并span使用给定时区中的适当时间更新标签内的值。
A simple jQuery example would be
一个简单的 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
});
});
I'm not posting the full code here, since there are plenty of JavaScript time formatters available with a simple search. Here's a few possible solutions
我不会在这里发布完整的代码,因为通过简单的搜索就可以使用大量的 JavaScript 时间格式化程序。这里有几个可能的解决方案
回答by Strika
There is a nice gem by Basecamp called local_time for client side rendering - https://github.com/basecamp/local_time. It's great for applications where user is not signed in and it's caching friendly.
Basecamp 有一个很好的 gem,称为 local_time 用于客户端渲染 - https://github.com/basecamp/local_time。它非常适合用户未登录且缓存友好的应用程序。
回答by John Naegle
You can add this to your application controller to convert all times to the User's timezone:
您可以将此添加到您的应用程序控制器以将所有时间转换为用户的时区:
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
You just have to capture the user's timezone
您只需要捕获用户的时区
回答by Richard Luck
Assuming that the value you want displayed is coming from the database, :ie started_atand is (as is the default) stored in UTC.
假设您想要显示的值来自数据库, :iestarted_at并且(默认情况下)以 UTC 存储。
If you have the user's timezone as an offset you can also localize the time by doing:
如果您将用户的时区作为偏移量,您还可以通过执行以下操作来本地化时间:
started_at.in_time_zone(-2)
=> Mon, 24 Feb 2014 23:07:56 GST -02:00
Which then can be munged in all sorts of way to get the parts you want:
然后可以通过各种方式对其进行加工以获得您想要的零件:
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
回答by Asad Hameed
If you'd like to convert your date to a specific Timezone:
如果您想将日期转换为特定时区:
deadline.in_time_zone(time_zone)
Here deadline is a date.
这里的截止日期是一个日期。
In addition, you can find Universal time through your local machine Timezone plus local time and vice verse, like in Karachi - +05:00, you can simply add it to value in Universal time to find time in your time zone or get Universal time from your local time by subtraction of Timezone difference (05:00 in our case) from your local time
此外,您可以通过您的本地机器时区加上当地时间,反之亦然,例如在卡拉奇 - +05:00,您可以简单地将其添加到世界时的值中以查找您所在时区的时间或获得世界时从您的当地时间减去时区差异(在我们的例子中为 05:00)从您的当地时间
回答by Trip
http://api.rubyonrails.org/classes/Time.html#method-c-use_zone
http://api.rubyonrails.org/classes/Time.html#method-c-use_zone
This is what you're looking for :
这就是你要找的:
Time.use_zone(@user.timezone) do
blah blah blah
end
回答by Dagmar
My jquery is a rusty, so it took me a little while to figure out how to implement the client-side approach of the accepted answer above.
我的 jquery 生疏了,所以我花了一点时间来弄清楚如何实现上面接受的答案的客户端方法。
Here's my solution:
这是我的解决方案:
HTML:
HTML:
<span data-time="<%= last_message_at %>"> </span>
Jquery/Javascript:
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>
回答by aNoble
You might want to take a look at these links in addition to the one Ben posted:
除了 Ben 发布的链接之外,您可能还想看看这些链接:

