显示用户时区的时间戳

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

我正在开发一个查询 PostgreSQL 数据库的 Spring Boot 应用程序。

我有一个

timestamptz
专栏。我的应用程序的最终用户希望在自己的时区查看这些时间戳,并包含偏移量。例如,

给定一行包含

2023-08-10T12:00:00.000+00

用户从时区查询时

'US/Eastern'

然后他们应该看到的输出是

2023-08-10T08:00:00.000-04

听起来很简单,但考虑到会有来自不同时区的多个并发请求,我很难弄清楚如何处理这个问题。

如果我在 SQL 控制台中执行此操作,它会给出我想要的精确结果,

SET LOCAL TIME ZONE 'US/Eastern';
SELECT to_char('2023-08-10T12:00:00.000+00'::TIMESTAMPTZ, 'YYYY-MM-DD"T"HH24:MI:SS.MSOF');

2023-08-10T08:00:00.000000-04

但是,我不知道如何在我的 Spring Boot 应用程序中使用它。

  1. 根据我的基准测试,如果我尝试在代码中执行此操作,则会带来约 30% 的性能损失,这在本例中非常重要,因此如果可能的话,我希望完全使用 SQL 来执行此操作。
  2. 我无法在
    ;
     中执行由 
    PreparedStatement
  3. 分隔的两个单独的语句
  4. 我不想更改数据库的默认时区,因为可能有多个并发请求。
  5. 出于同样的原因,我不想更改 JVM 的默认时区。

因此,回答这些问题中的任何一个都会有很大的帮助:

  • 在jdbc中,有没有办法只为单个查询设置时区,而不影响其他并发查询?
  • 在 PostgreSQL 中,有没有办法可以在一行中表达上述 SQL(没有分号)?
postgresql jdbc spring-jdbc
2个回答
0
投票

只需使用子句

at time zone
将服务器的时间戳转换为用户的时区,这里是一个例子:

select '2023-08-10T12:00:00.000+00' original_timestamptz
,'2023-08-10T12:00:00.000+00' at time zone 'US/Eastern' converted,
split_part(to_char('2023-08-10T12:00:00.000+00' at time zone 'US/Eastern', 
'YYYY-MM-DD"T"HH24:MI:SS.MSOF'),'+',1)||
(select split_part(utc_offset::text,':',1) from pg_timezone_names where name = 'US/Eastern')
with_offset;

有必要“手动”将偏移量添加到所需结果,因为表达式

timestamp with time zone AT TIME ZONE zone
返回
timestamp without time zone
,如 官方文档

中所示

0
投票

事实证明这相当复杂。这是我通过结合 Pepe 的回答和评论中的所有想法而提出的满足原始要求的函数:

CREATE OR REPLACE FUNCTION display_at_zone(
    tstz         TIMESTAMPTZ,
    display_zone VARCHAR
) RETURNS VARCHAR
AS
$$
DECLARE
    at_zone        TIMESTAMP;
    utc_offset     INTERVAL;
    hours          INT;
    minutes        INT;
    string_no_zone VARCHAR;
BEGIN

    at_zone = tstz AT TIME ZONE display_zone;
    utc_offset = at_zone - tstz;
    hours = EXTRACT(HOURS FROM utc_offset);
    minutes = ABS(EXTRACT(MINUTES FROM utc_offset));
    string_no_zone = TO_CHAR(at_zone, 'YYYY-MM-DD"T"HH24:MI:SS.MS');

    RETURN string_no_zone || TO_CHAR(hours, 'SG00:') || TO_CHAR(minutes, 'FM00');

END
$$ IMMUTABLE LANGUAGE plpgsql;

这(至少)有两个问题:

  1. 与使用
    java.time
    执行完全相同的操作相比,性能是 更差,而不是更好。
  2. 如果
    display_timezone
    参数是偏移量,则不起作用,但这可以轻松解决。
© www.soinside.com 2019 - 2024. All rights reserved.