我正在尝试添加时区到目前为止,这导致了一个奇怪的结果。 这是我的查询
SELECT timezone('GMT+5:30','2014-03-15'::date);
结果值为
"2014-03-14 13:00:00" (timestamp without timezone)
任何人都可以解释为什么它会为“2014-03-15”返回“2014-03-14 13:00:00”
我的时区是Asia/Calcutta(GMT+5:30)
答案 0 :(得分:1)
正如您所知,PostgreSQL允许函数重载
要检查名为timezone
的所有可能函数,请运行以下查询:
SELECT proname,pg_get_function_result(oid),pg_get_function_arguments(oid)
FROM pg_catalog.pg_proc
WHERE proname ~ '^timezone$';
如您所见,他们都没有接受date
类型作为参数。事实上它是非常有效的,因为没有时间成分,时区没有意义
因此,您将输入转换为timestamp with time zone
(基于您提到的结果数据类型),2014-03-15 00:00:00+XX
,其中XX
取决于您的位置。
并且,如果您的位置远远超过GMT
,则会导致时间减法,以便在所需区域返回时间戳。
此查询报告的内容:
SELECT current_timestamp, setting
FROM pg_settings
WHERE name = 'TimeZone';
<强>更新强>
是的,这个是棘手的东西。我强烈建议您多次阅读this answer。
请执行以下操作:
SET TimeZone TO 'Asia/Calcutta'; -- you don't have to do this
SELECT ts AT TIME ZONE 'UTC', ts AT TIME ZONE 'UTC' AT TIME ZONE 'UTC',
row_number() OVER () rn
FROM (VALUES (now()),
/* 2 */ ('2014-03-15'::date),
/* 3 */ ('2014-03-15'::date::timestamptz),
/* 4 */ ('2014-03-15'::date::timestamptz AT TIME ZONE 'UTC'),
/* 5 */ ('2014-03-15'::date::timestamptz AT TIME ZONE 'UTC' AT TIME ZONE 'UTC'),
/* 6 */ ('2014-03-15'::timestamp),
/* 7 */ (timezone('GMT+5:30','2014-03-15')),
/* 8 */ (timezone('GMT+5:30','2014-03-15'::date)),
/* 9 */ (timezone('GMT+5:30','2014-03-15'::timestamp)),
/*10 */ (timezone('GMT+5:30','2014-03-15'::timestamp) AT TIME ZONE 'UTC'),
/*11 */ (timezone('GMT+5:30','2014-03-15'::timestamptz)),
/*12 */ (timezone('GMT+5:30','2014-03-15'::timestamptz) AT TIME ZONE 'UTC')) t(ts);
并检查输出。
您的案例对应于此行#4
。你这里有2014-03-14 18:30:00
,
但是当你在时区+05:30
并且功能应该返回timestamp without time zone
时,你就会得到2014-03-14 13:00:00
。
请找到更多回合these types in the manual以及check AT TIME ZONE
构建。