2

在我的本地机器上,我使用的是 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

有什么想法可以让登台服务器上的解析结果识别时区吗?

4

1 回答 1

4

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

为什么

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

在您的情况下,您的字符串是由默认的 javascript 方法输出的,该方法Date.prototype.toString通常提供 RFC 1123 格式(但因实现而异),这对于RFC2822ISO8601来说大多已过时。

关于不同时间标准的说明(RFC、RFC、RFC!)

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

回到我们的红宝石

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

使用标准时间格式

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

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

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

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

于 2013-02-27T12:58:34.093 回答