不能正确地使用Date()函数进行转换。
将时间戳转换为日期会导致错误的日期,如果它是PST太多下午4点。
在这种情况下2012-06-21应该是2012-06-20。
starts_at列数据类型是没有时区的时间戳。这是我的查询:
没有转换到PST时区:
Select starts_at from schedules where id = 40; starts_at --------------------- 2012-06-21 01:00:00
转换给出了这一点:
Select (starts_at at time zone 'pst') from schedules where id = 40; timezone ------------------------ 2012-06-21 02:00:00-07
但是不能将时区转换为正确的日期。
基本上,Postgresql总是在时间段内存储时间戳的UTC时间值。只有显示因当前时区设置而异。 AT TIME ZONE
构造的效果也随基础数据类型而变化。 this related answer更多细节。
如果从timestamp [without time zone]
类型中提取日期,则可以获取当前时区的日期。输出中的日期与显示时间戳值相同。
如果从timestamp with time zone
类型(简称为timestamptz)中提取日期,则首先“应用”时区偏移。您仍然可以获取当前时区的日期,这与时间戳的显示一致。同样的时间点在欧洲的部分地区,例如在加利福尼亚州的下午4点。要获取某个时区的日期,请首先应用AT TIME ZONE。
因此,你在这个问题的顶部所描述的内容与你的例子相矛盾。
给定starts_at是时间戳[无时区],服务器上的时间设置为本地时间。测试与:
SELECT now();
它与墙上的时钟同时显示吗?如果是,您当前会话的时区设置与您当地的时区一致。如果否,您可能需要访问postgresql.conf中的时区设置。或者你的客户端可以做什么呢? (可以每个会话设置。)Details in the manual.
从start_at获取当地的日期
SELECT starts_at::date
重要的是:
SELECT date(starts_at)
BTW,您当地的时间现在是UTC-7,而不是UTC-8,因为夏令时是有效的(不是在人类的更明亮的想法之中)。
太平洋标准时间(PST)通常比UTC(通用时区)早8小时,但在夏令时期间(如现在)为7小时。这就是为什么timestamptz在你的例子中显示为2012-06-21 02:00:00-07。 AT TIME ZONE’PST’的结构考虑到夏令时。这两个表达式产生不同的结果(一个在冬天,一个在夏天),并且可能导致不同的日期:
SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST','2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST'