您可能知道,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 构造的信息。