为什么Ruby续作和Postgres psql的时区信息不同



以下是Postgres:的查询结果

$ psql ... -c 'select the_date from foo where foo_id in (998,999)'
     the_date      
------------------------
 2012-03-07 09:34:47.98
 2012-03-16 11:31:25.336

日期是"没有时区的时间戳"。

这里有一个Ruby程序:

#!/usr/bin/env ruby
require 'sequel'
@DB = Sequel.connect({...})
query = "select the_date from foo where foo_id in (998,999)"
@DB[query].each do |row|
  warn row
end

以及一些输出:

{:the_date=>2012-03-07 09:34:47 -0600}
{:the_date=>2012-03-16 11:31:25 -0500}

0500和0600是从哪里来的?这是服务器和客户端机器(US/Central)的"Olson时区",但为什么Ruby添加了它,而psql没有?

我一直在看那些文件,我完全弄糊涂了。

服务器为Postgres 9.0.4,客户端为psql 9.1.4,续作为3.33.0。

该列的类型为"timestamp without timezone"。因此,当Postgres在该列中显示值时,它只显示没有时区的时间戳。然而,Sequel希望将Postgres时间戳转换为Ruby Time类的实例,并且Time类的一个实例必须指定一个时区——要么是本地时区的时间,要么是UTC的时间。因此Sequel必须选择一个。默认情况下,它会选择您的本地时区。

您可以在Sequel中配置数据库和应用程序时区。看见https://www.rubydoc.info/gems/sequel/4.36.0/Sequel/Timezones

例如,以下是我手边的数据库的默认Sequel行为:

>   c['select * from actors'].each do |row|; puts row[:created_at]; end
Thu Jul 12 20:33:17 -0400 2012

这里的时间戳假设在我的本地时区(EDT)。

然而,如果我这样做:

> Sequel.database_timezone = :utc
 => :utc 
> c['select * from actors'].each do |row|; puts row[:created_at]; end
Thu Jul 12 20:33:17 UTC 2012

然后,时间戳假定为UTC。

我与ruby和日期/时间/时间戳打过一些奇怪的交道。看起来程序正试图将结果转换为已知的数据类型并自动进行强制转换,这就是为什么最后会收到5位数的时区代码。

相关内容

  • 没有找到相关文章