【发布时间】:2012-01-04 05:21:38
【问题描述】:
首先,我意识到不推荐使用time with time zone。我将使用它,因为我正在将多个 time with time zone 值与我当前的系统时间进行比较,无论是哪一天。 IE。用户说每天从 08:00 开始,并在 12:00 结束时使用他们的时区,而不是系统时区。所以,我在一个表中有一个time without time zone 列,我们称之为SCHEDULES.time,我在另一个表中有一个UNIX 时区名称 列,我们称之为USERS.tz。
我的系统时区是'America/Regina',不使用夏令时,所以偏移量总是-06。
鉴于“12:00:00”的时间和“美国/温哥华”的 tz,我想将数据选择到 time with time zone 类型的列中,但我不想将时间转换为我的时间zone,因为用户实际上已经说过在温哥华的 12:00 开始,而不是在里贾纳。
因此,做:
SELECT SCHEDULES.time AT TIME ZONE USERS.tz
FROM SCHEDULES JOIN USERS on USERS.ID=SCHEDULES.USERID;
结果(目前):
'10:00:00-08'
但我真的很想要:
'12:00:00-08'
除了AT TIME ZONE 之外,我找不到任何有关将时区应用于时间的文档。有没有办法在没有字符操作或其他 hack 的情况下实现这一点?
更新: 这可以通过使用字符串连接、强制转换和 Postgres 时区视图来完成:
select ('12:00:00'::text || utc_offset::text)::timetz
from pg_timezone_names
where name = 'America/Vancouver';
但是,这相当慢。一定有更好的办法吧?
更新 2:
我为混乱道歉。 SCHEDULES 表不使用 time with time zone,我正在尝试通过组合 time without time zone 和 text 时区名称中的值来选择 time with time zone。
更新 3:
感谢所有参与(激烈)讨论的人。 :) 我已被说服放弃使用time with time zone 作为输出的计划,而是使用timestamp with time zone,因为它性能良好、更具可读性,并解决了我将要遇到的另一个问题,即时区滚动到新的日期。 IE。 'America/Vancouver' 中的 '2011-11-21 23:59' 是 'America/Regina' 中的 '2011-11-22'。
更新 4:
正如我在上次更新中所说,我选择了@MichaelKrelin-hacker 首次提出并@JonSkeet 最终确定的答案。也就是说,timestamp with time zone 作为我的最终输出是一个更好的解决方案。我最终使用了如下查询:
SELECT timezone(USERS.tz, now()::date + SCHEDULES.time)
FROM SCHEDULES
JOIN USERS ON USERS.ID = SCHEDULES.USERID;
timezone() 格式在我将(current_date + SCHEDULES.time) AT TIME ZONE USERS.tz 输入视图后被 Postgres 重写。
【问题讨论】:
-
你真正的SQL里面有join吗?目前我看不到你如何将一个映射到另一个。如果是这样,请显示一个简短但完整的查询。
-
是的,连接是隐含的。 SELECT SCHEDULES.time AT TIME ZONE USERS.tz from SCHEDULES JOIN USERS on USERS.ID=SCHEDULES.USERID
-
@JonSkeet:我不明白为什么有必要这样做,因为他给了我们具体的数据示例。如果有帮助,您可以假装完整的查询是
SELECT '12:00:00'::TIME AT TIME ZONE 'America/Vancouver';,它在 OP 的 GMT-0600 系统上给出10:00:00-08。 -
@ruakh:连接对于实际查询绝对是必要的 - 很明显,如果这被搞砸了,它会影响其他一切。
-
这让我很感兴趣。听起来它应该工作。我正在下载并安装 PostgreSQL 来尝试一下。准备好愚蠢的问题...
标签: sql postgresql time timezone