Postgres:如何为无时区时间指定时区(无需偏移及服务器时区信息)
问题:如何在不依赖服务器时区、自身位置,且无需提前知晓目标时区当前夏令时偏移的情况下,为time类型显式指定时区名称?
背景
后续要解决的核心问题是:无论服务器时区如何,判断纽约证券交易所是否开市(已知纽交所于美国东部时间16:00闭市,不受季节及夏令时影响)。
当前面临两个关键障碍:
- 无法提前知晓目标时区(美国东部)当前的夏令时偏移
- 不清楚服务器的时区设置及查询运行的物理位置
错误示例
以下是尝试过但不符合要求的写法:
select -- 这类写法解决了不知道当前偏移的问题,但需要知晓本地服务器时区设置 timezone('US/Eastern','16:00:00'::time without time zone) -- 输出示例:12:00:00.000000 -04:00 -- 错误原因:时区正确但时间值错误,隐含假设服务器时区为UTC(本次测试恰好符合,但不具备通用性) ,timezone('UTC', timezone('US/Eastern','16:00:00'::time without time zone)) -- 输出示例:16:00:00.000000 +00:00 -- 错误原因:时间值正确但时区未以US/Eastern标识,同样依赖服务器为UTC的隐含假设 -- 这类写法无需知晓服务器时区,但需要提前知道纽约当前的时区偏移(该偏移会随夏令时变化) ,'16:00:00.0 -04:00'::time with time zone -- 以及... ,timezone('US/Eastern', '16:00:00.0 -04:00'::time with time zone) -- 输出示例:16:00:00.000000 -04:00 -- 优点:不依赖服务器时区 -- 缺点:必须提前知晓当前偏移,不具备通用性,且后者属于重复操作
需求本质
我的需求可以概括为:如何查询Postgres的时区数据库(按时区名称),并将对应时区的偏移动态应用到无时区的time类型值上,类似如下(伪代码)写法:
select '16:00:00.0'::time with offset (select utc_offset from pg_timezone_names where name='US/Eastern')
解决方案
要实现这个需求,关键是将time without time zone与当前日期结合成timestamp without time zone,再指定时区转换为timestamp with time zone,最后提取time with time zone部分。这样Postgres会自动处理夏令时的偏移变化,无需手动指定:
-- 核心写法:将无时区时间绑定到当前日期,再指定目标时区 select (current_date + '16:00:00'::time)::timestamp without time zone at time zone 'US/Eastern'::time with time zone;
解释
current_date + '16:00:00'::time:生成一个无时区的日期时间(当天的16:00)at time zone 'US/Eastern':将这个无时区的日期时间转换为美国东部时区的带时区时间,Postgres会自动从时区数据库中获取当前(对应日期)的夏令时偏移- 最终得到的是带
US/Eastern时区标识的16:00时间值,完全不依赖服务器时区,也无需手动指定偏移
针对纽交所开市判断的场景,可以扩展为:
-- 判断当前时间是否在纽交所开市时段(美国东部时间9:30-16:00) select current_timestamp at time zone 'US/Eastern' between '09:30:00'::time and '16:00:00'::time as is_nyse_open;
内容的提问来源于stack exchange,提问作者cloudsurfin
相关产品推荐
相关产品推荐

