简体   繁体   English

使用TimeZone在MySQL DB中正确存储日期以用于Rails应用程序

[英]Correctly storing dates with TimeZone in MySQL DB for a Rails application

I'm looking at converting our Rails 2.3 application to correctly handle time zones (at the moment everything is in UTC which isn't right, but is convenient!). 我正在考虑转换我们的Rails 2.3应用程序以正确处理时区(目前所有内容都是UTC,这是不对的,但方便!)。

I have these settings in environment.rb: 我在environment.rb中有这些设置:

config.active_record.default_timezone = :utc
config.time_zone = "UTC"

Going forward, on each request in our app I plan on making the following setting to set the Time Zone: 继续,在我们的应用程序中的每个请求,我计划进行以下设置来设置时区:

Time.zone = user.time_zone

Where user.time_zone is their chosen preference (eg US Pacific Time ). user.time_zone是他们选择的偏好(例如US Pacific Time )。

This works fine in the app, but my question relates to what Rails then stores in the MySQL DB. 这在应用程序中运行良好,但我的问题与Rails然后存储在MySQL DB中有关。 If the user chooses a date of 1st June 2009, this gets stored in a DATETIME field in the database in UTC but with the time zone offset. 如果用户选择2009年6月1日的日期, DATETIME以UTC DATETIME存储在数据库的DATETIME字段中,但会使用时区偏移量。 For example, if the user has selected a GMT+6 time zone, a chosen date of 1st June 2009 ends up in the database as 2009-06-01 06:00:00 UTC . 例如,如果用户选择了GMT+6时区,则2009年6月1日的选定日期将在数据库中以2009-06-01 06:00:00 UTC

I would have expected this to be stored as 2009-06-01 00:00:00 UTC in the database. 我原以为这将在2009-06-01 00:00:00 UTC存储在数据库中。 Is my thinking correct or is Rails doing something unexpected here? 我的想法是正确的还是Rails在这里做了一些意外的事情?

This blog post talks about native Time zone handling in Rails 2.1+: 这篇博文讲述了Rails 2.1+中的本地时区处理:

http://mad.ly/2008/04/09/rails-21-time-zone-support-an-overview/ http://mad.ly/2008/04/09/rails-21-time-zone-support-an-overview/

The gist is that Rails will store all records in the DB in UTC and then convert to the users timezone for display. 要点是Rails将以UTC格式存储数据库中的所有记录,然后转换为用户时区进行显示。 Which makes sense: store all data in a neutral form, and then convert it to the desired form at the last minute. 这是有道理的:以中性形式存储所有数据,然后在最后一刻将其转换为所需的形式。

Based on your response to my comment, I'd say just store the date based on the local server time, then use JavaScript's Date::toLocaleString() to convert it to their local timezone. 根据您对我的评论的回复,我会说只是根据本地服务器时间存储日期,然后使用JavaScript的Date :: toLocaleString()将其转换为本地时区。 I wrote an article on it a couple of years ago, which you can find here . 几年前我写了一篇文章,你可以在这里找到。

The article's JS was written in MooTools, but I've since rewritten it with jQuery, so I'll show that code. 文章的JS是用MooTools编写的,但我已经用jQuery重写了它,所以我将展示代码。

The important parts: 重要的部分:

When rendering to HTML, use the milliseconds since Epoch. 渲染为HTML时,请使用自Epoch以来的毫秒数。

<span class="dt"><!-- <%= blah.created_at_epoch_ms %> --><%= blah.created_at %></span>

Which requires a method in your model defined like this: 这需要您的模型中定义的方法如下:

def created_at_epoch_ms
    self.created_at.to_i * 1000
end

The JS to transform the dates: JS改变日期:

$(document).ready(function(){
        $('span.dt').each(function(){
                var date = new Date();

                date.setTime(this.firstChild.data);

                $(this).parent().text(date.toLocaleString());
        });
});

This should convert the string to the user's local time, and the magic happens in toLocaleString(). 这应该将字符串转换为用户的本地时间,并且魔术发生在toLocaleString()中。 The only browser I've heard of that doesn't implement it is Safari 2.0, which shouldn't present much of a problem, as I think most users have moved on. 我听说过唯一没有实现它的浏览器是Safari 2.0,它不应该出现太多问题,因为我认为大多数用户已经开始了。

I use this method on my site , and if you look at the source code to the page, you can see what it does. 我在我的网站上使用此方法,如果您查看页面的源代码,您可以看到它的作用。 The actual code that's sent to the browser looks like: 发送到浏览器的实际代码如下所示:

<!-- 1243484521000 -->2009-05-28 04:22:01 UTC

Which is converted in my browser (Central Time) to 哪个在我的浏览器(中部时间)转换为

Wednesday, May 27, 2009 11:22:01 PM

If they have JS enabled, it'll take the value of the comment node, transform it, and replace the entire string (including the UTC time) with the local time. 如果他们启用了JS,它将获取注释节点的值,对其进行转换,并将整个字符串(包括UTC时间)替换为本地时间。 If JS is disabled, they'll just see the time as the server sees it. 如果JS被禁用,他们只会看到服务器看到它的时间。

在设置日期之前,需要在数据对象中设置时区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM