我需要在特定列中传递时区(操作_时区)
INSERT INTO segments (
operation_type, operation_time, operation_time_zone, operation_place,
passenger_name, passenger_surname, passenger_patronymic,
doc_type, doc_number, birthdate, gender, passenger_type,
ticket_number, ticket_type, airline_code, flight_num,
depart_place, depart_datetime, arrive_place, arrive_datetime,
pnr_id, serial_number)
VALUES (
$1,
($2 AT TIME ZONE 'UTC')::TIMESTAMP,
(EXTRACT(TIMEZONE FROM $2::TIMESTAMPTZ) / 3600)::SMALLINT,
$3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21
);
但是如果我这样通过的话,我在操作时区中得到0。 值 $2 是“2022-01-01T03:25:00+03:00”。 如果我执行这个查询
SELECT (EXTRACT(TIMEZONE FROM '2022-01-01T03:25:00+03:00'::TIMESTAMPTZ) / 3600)::SMALLINT AS timezone_in_hours;
我得到了3。
timezone
设置。
EXTRACT(TIMEZONE FROM $2::TIMESTAMPTZ)
您会得到
0
,这意味着您的会话在 UTC 时间(或在给定时间与格林威治没有偏移的相关时区)运行。 Postgres 时间戳数据类型 根本不存储任何时区信息 - 都不存储
timestamp with time zone
(timestamptz
)也不是timestamp without time zone
(timestamp
)。 timestamptz 值的 display 会根据会话的时区设置进行调整,即它始终与 EXTRACT
将看到的偏移量相同。
参见:
要保留
timestamptz
literal 中给出的时间偏移量,请将 $2
作为 text
传递,然后解析文本表示(这非常棘手!),或者使用以下表达式:
$2::timestamp AT TIME ZONE 'UTC' - $2::timestamptz
$2::timestamp
将 timestamptz
文字转换为 timestamp
,忽略时间偏移(这通常是一个偷偷摸摸的错误,但这次是故意的)。减去正确转换的 timestamptz
会产生文字中的有效时间偏移。这比字符串处理便宜,并且也适用于时区名称或缩写。考虑这个综合演示:
你的
INSERT
可以像这样工作:
INSERT INTO segments (
...
, operation_time
, operation_time_zone
, ...
)
VALUES (
...
, $2::timestamptz AT TIME ZONE 'UTC'
, EXTRACT(hour FROM $2::timestamp AT TIME ZONE 'UTC' - $2::timestamptz)::int2
, ...
)