时区解析ruby版本之间的差异

时间:2013-02-27 12:02:10

标签: ruby-on-rails ruby timezone

在我的本地计算机中,我正在使用RVM

>> ruby -v
=> ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

# in the terminal
>> date
=> Wed Feb 27 20:00:17 PHT 2013

在我们的登台服务器中,我们使用的是rbenv

>> ruby -v
=> ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

# in the terminal
>> date
=> Wed Feb 27 12:00:22 UTC 2013

在我的本地计算机中,我正在解析来自ajax调用的日期字符串

>> Time.zone
=> (GMT+00:00) UTC
>> Time.zone.parse('Wed Feb 27 2013 19:46:21 GMT+0800 (PHT)')
=> Wed, 27 Feb 2013 19:46:21 UTC +00:00

在我们的登台服务器中,我得到了不同的结果

>> Time.zone
=> (GMT+00:00) UTC
>> Time.zone.parse('Wed Feb 27 2013 19:46:21 GMT+0800 (PHT)')
=> Wed, 27 Feb 2013 11:46:21 UTC +00:00

如何在登台服务器上进行解析结果的任何想法都能识别出时区?

1 个答案:

答案 0 :(得分:3)

Javascript和Ruby不使用相同的时间格式,因此存在差异。一个Javascript使用(RFC 1123)是过时的,并且被一些(但不是全部!)Ruby日期时间解析方法实现读取错误,这些实现需要类似RFC 2822或ISO 8601.这种差异通过将Javascript输出到ISO格式。

为什么

您正在使用的

ActiveSupport::TimeZone#parse内部直接在字符串上使用Time::parse来获取时间,然后将其放入所需的时区。

在你的情况下,你的字符串是由默认的javascript方法Date.prototype.toString输出的,它通常提供RFC 1123格式(但因实现而异),这大部分已经过时RFC2822和{{3 }}。

关于不同时间标准(RFC,RFC,RFC!)

的说明

RFC1123允许使用“GMT”字符串表示时区,例如“GMT + 0800”,而ISO8601则废弃该字符串,支持统一的UTC表示“+0800”,而不说“GMT”/“UT ”。 ISO8601更加紧凑(例如20130227T0914-0500),所以也不允许说“GMT”。

回到我们的红宝石

因此,使用RFC2822Time::parse无法识别时区信息(特别是与“GMT”混淆),并且会回退到系统时区。

使用标准时间格式

事实上,正如Saurabh指出的那样,这是客户端如何将时间序列化为字符串的问题。我建议更改已解析的字符串以使用标准格式,如Time::zone_offset(类似于您的格式)或RFC2822。在这种情况下,您的时间应该正确解析。

irb(main):049:0> Time.zone.parse('Wed Feb 27 2013 19:46:21 GMT+0800 (PHT)')
=> Thu, 28 Feb 2013 00:46:21 UTC +00:00
irb(main):050:0> Time.zone.parse('Wed Feb 27 2013 19:46:21 +0800 (PHT)')
=> Wed, 27 Feb 2013 11:46:21 UTC +00:00

在我刚刚做的快速测试中,Javascript似乎无法轻松输出RFC 2822字符串(没有“GMT”)。但是,暂时不要离开你的gsub,不能保证永远存在“GMT”或“UTC”。幸运的是,ISO似乎很容易做到。 (如果格式符合你的想象,那就是; o))

> new Date();
Wed, 27 Feb 2013 13:22:20 GMT # bad
> (new Date()).toString();
'Wed Feb 27 2013 08:22:25 GMT-0500 (EST)' # bad
> (new Date()).toUTCString();
'Wed, 27 Feb 2013 13:22:31 GMT' # still bad :(
> (new Date()).toISOString();
'2013-02-27T13:22:57.310Z' # good

无法触摸此! (Javascript客户端)

或者,如果改变客户端是不可能的,或者您正在寻找快速而肮脏的修复方法,那么您可以使用Date::_parse代替它,它似乎正确地计算出您的偏移量。

irb(main):052:0> d = Date._parse('Wed Feb 27 2013 19:46:21 +0800 (PHT)')
=> {:wday=>3, :zone=>"+0800", :hour=>19, :min=>46, :sec=>21, :year=>2013, :mon=>2, :mday=>27, :offset=>28800}
irb(main):053:0> Time.new(d[:year], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:offset])
=> 2013-02-27 19:46:21 +0800

但是,我不确定这个方法是否可以长期依赖,因为它使用内部日期解析函数。此外,使用标准时间字符串可能是个好主意。

所以记住小孩,标准是你的朋友!使用它们!