postgresql - 为啥 now() 保存后不正确?

Posted

技术标签:

【中文标题】postgresql - 为啥 now() 保存后不正确?【英文标题】:postgresql - why is now() is not right after saving?postgresql - 为什么 now() 保存后不正确? 【发布时间】:2021-10-01 02:32:04 【问题描述】:

原来是这样,我有这样的程序:

CREATE OR REPLACE PROCEDURE public.savetrbankd(
    _transcode text,
    _id integer,
    _expensecode text,
    _debetamt numeric,
    _creditamt numeric)
LANGUAGE 'plpgsql'
AS $BODY$
Declare 
BEGIN
If _id=0 Then
    INSERT INTO trbankd(transcode,expensecode,ket,debetamt,creditamt)
    VALUES(_transcode,_expensecode,_ket,_debetamt,_creditamt);
Else
    UPDATE trbankd SET 
        expensecode=_expensecode,
        debetamt=_debetamt,
        creditamt=_creditamt,
        LastUpdatedDate=now()
    WHERE transcode=_transcode and id=_id;
END IF;
END;
$BODY$;

让我们注意这里的“lastupdateddate”字段。类型为不带时区的timestamp,默认值为now()。

所以在使用此过程插入/更新记录后,我尝试再次查询数据。 所以我得到了: 2021-07-23 23:48:42.805869

但是当我插入/更新记录时,应该是 2021 年 7 月 24 日下午 1 点左右。 所以我们得到了大约 13-14 小时的时区差异?

当然,然后当我尝试显示时区时,它说是我们/太平洋。 然后我将时区设置为 asia/bangkok(这是我的真实时区),代码如下:set timezone='Asia/Bangkok'。 数据没有改变。它仍然说 lastupdateddate 是 2021 年 7 月 23 日。 好的,也许之前输入的数据不会改变,因为我使用了没有时区类型的时间戳。所以我尝试使用存储过程再次更新数据,它仍然显示 2021-07-24 00:29:23.384443

所以它仍然是大约 13-14 小时的相同差异。 我如何确保插入和查询的数据与服务器(恰好是我的计算机)相同。 作为补充说明,我的设置控制面板区域是我们(英语),我的位置已设置为印度尼西亚(gmt +7),并且我当前在计算机上的时间是正确的(就像我在上面所说的那样是下午 1-2 点)。

提前谢谢

【问题讨论】:

注意:now()后面多了一个逗号 抱歉,我的剪辑不好。真正的存储过程实际上要长得多,所以我剪掉它只是为了让你知道图片。我已经修好了。我向你保证,真正的存储过程运行良好,之前没有这样的错误语法。 【参考方案1】:

您发现将时间戳数据存储在timestamp without time zone 字段中通常不是一个好主意,尤其是在跨时区工作时。有关 timestamp without time zone(timestamp) 和 timestamp with time zone(timestamptz) 如何处理时间戳的详细信息,请参见此处:

https://www.postgresql.org/docs/current/datatype-datetime.html

8.5.1.3。时间戳

为了说明你所看到的:

select '2021-07-23 23:48:42.805869'::timestamp AT time zone 'US/Pacific';
           timezone            
-------------------------------
 2021-07-23 23:48:42.805869-07


select '2021-07-23 23:48:42.805869'::timestamp AT time zone 'US/Pacific' AT time zone 'Asia/Bangkok';
          timezone          
----------------------------
 2021-07-24 13:48:42.805869

---Current time here(I'm in 'US/Pacific')

test(5432)=# show timezone;
  TimeZone  
------------
 US/Pacific
(1 row)

test(5432)=# select now()::timestamp;
            now             
----------------------------
 2021-07-24 08:57:07.780014

                  
test(5432)=# set timezone = 'Asia/Bangkok';
SET
test(5432)=# select now()::timestamp;
            now             
----------------------------
 2021-07-24 22:56:14.659657



now() 正在获取服务器中设置的时区(或通过客户端重置)并使用它来创建时间戳。由于它被存储到timestamp,因此没有时区偏移。您处理此问题的选择是:

    保持原样,timestamp without time zone 字段和timezone='US/Pacific'。根据需要转换为本地时区。

    将字段转换为timestamp with time zone。不过,在执行此操作之前,您需要确定您知道当前值实际代表什么。

【讨论】:

抱歉,这几周太忙了。所以我现在就检查一下。是的。我知道区别(或者我认为我做到了)我没有提到和强调的是,这发生在我的电脑上。我的计算机是网络服务器,我从中调用了该程序,这就是我困惑的根源,因为这一切都发生在一台计算机上,即我的计算机上。 now() 函数应该得到我电脑上的时间,不管是哪个区域,都应该是一样的,因为我从来没有改变过我电脑的区域。我只是因为这个奇怪的问题而搞乱了这个地区。 底线是now() 将使用TimeZone 在运行时设置的任何值。根据您的问题,您说 Postgres 中的默认时区设置为 US/Pacific。如果您想让自己更轻松,请使用timestamp with time zone 字段。时间戳实际上并没有与时区一起存储,它只是旋转到并存储为UTC。那么你总是有一个已知的价值起点。

以上是关于postgresql - 为啥 now() 保存后不正确?的主要内容,如果未能解决你的问题,请参考以下文章

模型中的 Django default=datetime.now() 在 uwsgi 重置后总是保存相同的日期时间

PostgreSQL now()函数没有返回时间

为啥 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象?

PostgreSQL (简称gp)小集

postgresql 日期格式

装postgresql时为啥连接失败