【问题标题】:Why does timezone info from Ruby sequel and Postgres psql differ?为什么来自 Ruby sequel 和 Postgres psql 的时区信息不同?
【发布时间】:2012-07-30 21:31:51
【问题描述】:

这是来自 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

the_date 是“没有时区的时间戳”。

这是一个 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 从何而来?那是服务器和客户端机器(美国/中部)的“Olson timezone”,但是为什么Ruby添加它而psql没有呢?

我一直在阅读the docs,我完全糊涂了。

服务器是Postgres 9.0.4,客户端是psql 9.1.4,sequel是3.33.0。

【问题讨论】:

标签: ruby postgresql timezone


【解决方案1】:

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

您可以在 Sequel 中配置数据库和应用程序时区。见http://sequel.rubyforge.org/rdoc/classes/Sequel/Timezones.html

例如,下面是我方便使用的数据库的默认 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。

【讨论】:

  • 很好的答案,谢谢。所以 Sequel 的“本地时间戳”行为足够复杂,可以根据时间戳本身考虑夏令时(因此是 -0500 和 -0600)?
  • 是的——尽管这种复杂性实际上来自 Ruby 的 Time 类。例如,对于东部地区的我来说, Time.parse('2012-03-07 09:34:47').to_s 给出“Wed Mar 07 09:34:47 -0500 2012”,而 Time.parse(' 2012-03-16 11:31:25').to_s 给出“2012 年 3 月 16 日星期五 11:31:25 -0400”。
【解决方案2】:

我对 ruby​​ 和日期/时间/时间戳进行了一些奇怪的处理。看起来程序正在尝试将结果转换为已知的数据类型并自动转换它,这就是为什么您会在最后收到 5 位时区代码。

【讨论】:

    猜你喜欢
    • 2011-12-17
    • 2011-01-20
    • 2019-10-25
    • 2015-01-11
    • 2021-12-17
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 2019-04-30
    相关资源
    最近更新 更多