基本上你想要的是:
$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40
我从这篇文章的解决方案是下面,这是直的黄金!它非常清楚地解释了这个不重要的问题,如果您希望更好地理解pstgrsql TZ管理,请给它一个解读。
Expressing PostgreSQL timestamps without zones in local time
这里是正在发生的事情。首先,您应该知道“PST时区比UTC时区晚8小时,因此例如2014年1月1日,太平洋标准时间下午4:30(周三,2014年1月1日16:00:30 -0800)相当于2014年1月2日00:30上午UTC(周四,2014年1月2日00:00:30 +0000)。任何时候在太平洋标准时间下午4点后到第二天,解释为UTC。
另外,正如Erwin Brandstetter上面提到的,postresql有两种类型的时间戳数据类型,一种带有时区,另一种没有时区。 如果时间戳包括时区,然后进行简单:
$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40
会工作。但是,如果您的时间戳是无时区的,执行上述命令将不起作用,您必须首先将您的无时区时间戳转换为带有时区(即UTC时区)的时间戳,然后将其转换为所需的'PST'或'US /太平洋'(这是相同的一些夏令时问题,我认为你应该罚款)。
让我演示一个例子,我创建一个无时区的时间戳。为方便起见,假设我们当地的时区确实是'PST'(如果不是这样,它会变得稍微复杂一些,这对于此解释来说是不必要的)。
说我有:
$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
这将产生:
"a"=>"2014-01-02 00:30:00" (This is the timezoneless timestamp)
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one)
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion)
"d"=>"2014-01-02 08:30:00+00"
最后的时间戳是所有关于PostgreSQL的UTC的转换timezoneless时间戳 'PST' 混乱的原因。当我们写:
timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
我们正在采取timezoneless时间戳,并尝试将其转换为“PST TZ(我们间接地假设PostgreSQL将明白,我们希望它的时间戳从UTC TZ转换,但postresql有它自己的计划!)。在实践中,postgresql所做的是需要无时区的时间戳('2014-01-2 00:30:00),并将其视为它已经实现了'PST'TZ时间戳(即:2014-01-2 00:30:00 :00 -0800)并将其转换为UTC时区!所以它实际上推动了8小时而不是回来!因此我们得到(2014-01-02 08:30:00 + 00)。
无论如何,这最后(不直观)的行为是造成所有混淆的原因。如果你想要更全面的解释,请阅读文章,其实我得到的结果与最后一部分有所不同,但总的想法是一样的。
这是正确的 - 'PST'不考虑夏时制,请参阅John Rennpferd关于使用“US/Pacific”与“PST”或“PDT”的答案 –