在我的本地计算机中,我使用 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
有什么想法可以让临时服务器上的解析结果识别时区吗?
最佳答案
Javascript 和 Ruby 不使用相同的时间格式,因此存在差异。 Javascript 使用的一个 (RFC 1123) 已过时,并且被一些(但不是全部!)Ruby 日期时间解析方法实现读取错误,这些实现需要类似于 RFC 2822 或 ISO 8601 的内容。通过将 Javascript 输出设置为ISO 格式。
原因
您正在使用的 ActiveSupport::TimeZone#parse
,在内部直接在字符串上使用 Time::parse
来获取时间,然后将其放入所需的时区。
在您的情况下,您的字符串是由默认的 javascript 方法 Date.prototype.toString
输出的,该方法通常提供 RFC 1123 格式(但因实现而异),该格式大部分已过时为 RFC2822 和ISO8601 。
关于不同时间标准的说明(RFC、RFC、RFC!)
RFC1123 允许使用“GMT”字符串表示时区,例如“GMT+0800”,而 RFC2822 废弃该字符串,转而采用统一的 UTC 表示“+0800”,而不用说“GMT”/“UT”。 ISO8601 更加紧凑(例如20130227T0914-0500
),因此也不允许说“GMT”。
回到我们的 ruby
因此,使用 Time::zone_offset
的 Time::parse
无法识别该时区信息(特别是与“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
但是,我不确定这个方法是否可以长期依赖,因为它使用内部日期解析函数。此外,使用标准时间字符串可能是个好主意。
所以记住 children ,标准是你的 friend !使用它们!
关于ruby-on-rails - ruby 版本之间的时区解析差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15111621/