Rails/PostgreSQL 日期SQL差异

5
在 psql 中运行以下查询,我得到了 7 个结果:
SELECT generate_series('2012-10-14', CURRENT_DATE, interval '1 day'); # 7

然而,当我在我的Rails应用程序中运行完全相同的查询时,我得到了8个结果:
result = ActiveRecord::Base.connection.execute "SELECT generate_series('2012-10-14', CURRENT_DATE, interval '1 day');"
puts result.count # 8

看起来这似乎与时区有关,但我不知道问题出在哪里。我在我的application.rb中添加了以下内容:

config.time_zone = 'Eastern Time (US & Canada)'

这是我在postgresql.conf中设置的相同时区。

我对为什么我的Rails应用程序会在结果中添加一天感到困惑。是否有人可以提供一些见解?

这似乎只发生在一天结束时(晚上8点之后),这让我觉得这可能与时区偏移有关。

1个回答

9
您使用的版本的 generate_series 函数处理的是时间戳而不是日期。因此,您的'2012-10-14'current_date将被转换为带时区的timestamp,并且generate_series函数生成一组带有时区的timestamp数据;请参考以下内容:
=> select generate_series('2012-10-14', current_date, '1 day');
    generate_series     
------------------------
 2012-10-14 00:00:00-07
 2012-10-15 00:00:00-07
 2012-10-16 00:00:00-07
 2012-10-17 00:00:00-07
 2012-10-18 00:00:00-07
 2012-10-19 00:00:00-07
 2012-10-20 00:00:00-07
(7 rows)

=> select generate_series('2012-10-14', current_date::timestamp, '1 day');
   generate_series   
---------------------
 2012-10-14 00:00:00
 2012-10-15 00:00:00
 2012-10-16 00:00:00
 2012-10-17 00:00:00
 2012-10-18 00:00:00
 2012-10-19 00:00:00
 2012-10-20 00:00:00
(7 rows)

第一个具有时区,而第二个则没有。

但是,current_date总是会被转换为带有数据库会话的时区调整的时间戳。Rails会话将以UTC与数据库交互,而您的psql会话可能正在使用ET。

如果您手动指定当前日期并明确使用timestamp

select generate_series('2012-10-14'::timestamp, '2012-10-20'::timestamp, '1 day')

如果没有涉及到时区问题,那么两个相同的查询将会得到相同的七个结果。

忽略时区的最简单方法是使用generate_series的整数版本,并且利用将整数加到日期上的方式,这里整数被视为天数:

select '2012-10-14'::date + generate_series(0, 6)

这样可以避免时区干扰,让你拥有相同的七天。你仍然可以使用current_date(由于SQL日期没有时区,因此没有时区), 只需要注意两个日期之间的差异就是它们之间的天数(一个整数):

=> select '2012-10-14'::date + generate_series(0, current_date - '2012-10-14');
  ?column?  
------------
 2012-10-14
 2012-10-15
 2012-10-16
 2012-10-17
 2012-10-18
 2012-10-19
 2012-10-20
(7 rows)

同时还有来自Rails的:

> pp ActiveRecord::Base.connection.execute("select '2012-10-14'::date + generate_series(0, 6)").to_a
[{"?column?"=>"2012-10-14"},
 {"?column?"=>"2012-10-15"},
 {"?column?"=>"2012-10-16"},
 {"?column?"=>"2012-10-17"},
 {"?column?"=>"2012-10-18"},
 {"?column?"=>"2012-10-19"},
 {"?column?"=>"2012-10-20"}]

顺便说一句,我讨厌时区,非常讨厌和鄙视它们。


2
+1 非常好的解释。顺便说一下,我保留我的“憎恨”给愚蠢的夏令时概念,它既不节省任何日光也没有任何意义。只会在全世界造成混乱浪费大量时间。应该消除夏令时并永远不再提及。 - Erwin Brandstetter
2
@ErwinBrandstetter:我不能在一个不鼓励说脏话的公共论坛上谈论DST,我就是做不到。 - mu is too short
感谢您深入的解释,尽管这让我更加讨厌时区 ;) - Kyle Decot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接