如何在postgresql中插入时区

问题描述 投票:0回答:1

我需要在特定列中传递时区(操作_时区)

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。

sql database postgresql go extract
1个回答
0
投票

说明

此表达式仅反映当前会话的

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
 , ...
   )
© www.soinside.com 2019 - 2024. All rights reserved.