database - PostgreSQL 时间戳字段中的数据损坏

标签 database postgresql rdbms

我有一个具有以下模式的 PostgreSQL 表 -

CREATE TABLE test (
  id serial NOT NULL PRIMARY KEY,
  username varchar(100) NOT NULL, -- The user name
  dob timestamp with time zone NOT NULL -- The date of birth
);

然后我将一些数据插入到表中,数据如下 -

INSERT INTO "test" ("username", "dob") VALUES (E'Scotty', E'2009-05-14 15:44:43');

如果我检查数据库中的数据,我会得到这个 -

mydb=> select username, dob from test where username='Scotty';
 username |            dob            
----------+---------------------------
 Scotty   | 2009-05-14 15:44:43+05:30
(1 row)

在我尝试插入一些日期早于 1946 年的数据之前,一切都很好,花花公子 -

INSERT INTO "test" ("username", "dob") VALUES (E'James T Kirk', E'1945-01-01 11:30:11');

mydb=> select username, dob from test where username='James T Kirk';
      username |            dob            
-------------- +---------------------------
 James T Kirk  | 1945-01-01 11:30:11+06:30
(1 row)

看上面的结果。请注意时区值如何从 +05:30 更改为 +06:30

当我插入 1942 年之前的任何日期时,情况实际上变得更糟 -

INSERT INTO "test" ("username", "dob") VALUES (E'Spock', E'1941-01-01 11:30:11');

mydb=> select username, dob from test where username='Spock';
 username |             dob              
----------+------------------------------
 Spock    | 1941-01-01 11:30:11+05:53:20
(1 row)

现在 Timezone 值已完全损坏,无法解析日期。

我将不胜感激。

我的时区是亚洲/加尔各答 (GMT+05:30)。

更新:我尝试通过像这样明确指定 TZ 来输入数据 -

INSERT INTO "test" ("username", "dob") VALUES (E'McCoy', E'1941-01-25 00:20:30+05:30');

即使那样它也没有用。

mydb=> select username, dob from test where username='McCoy';
 username |             dob              
----------+------------------------------
 McCoy    | 1941-01-25 00:43:50+05:53:20
(1 row)

最佳答案

在哪个地区?可能 PostgreSQL 假设日期适用于您当前的语言环境,并应用适当的时区和 DST 规则,如果日期和时间是(比如)UTC,这不是正确的做法。

您真的需要时区功能吗? 没有时区的时间戳 将表现出更明智的行为,因为它不必实现奇怪的规则。但是,如果您需要时区,那么您肯定希望修复它而不是弄乱它。

最好的解决办法就是明确指定时区:'04:05:06-08:00' 用于 GMT–08:00,或者 '04:05:06z ' 用于 GMT/UTC/“Zulu”(因此是“z”)。

编辑:大部分真正的怪异现象来自亚洲/加尔各答时区。来自 tzdata2009g:

# India
# Zone  NAME        GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Asia/Kolkata    5:53:28 -   LMT 1880    # Kolkata
            5:53:20 -   HMT 1941 Oct    # Howrah Mean Time?
            6:30    -   BURT    1942 May 15 # Burma Time
            5:30    -   IST 1942 Sep
            5:30    1:00    IST 1945 Oct 15
            5:30    -   IST

你没有描述你期望的行为是什么,所以很难说你想从这里去哪里。

关于database - PostgreSQL 时间戳字段中的数据损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/862681/

相关文章:

database - 了解 3NF

postgresql - 单个事务中的多个 SELECT FOR UPDATES 是否会导致竞争条件 (Postgres)?

sql - hstore 中没有可预测键的索引

sql - SQL 中的业务逻辑关系

mysql - SQL - 扣除列值直到非负值

php - 将具有 unix 时间戳值的 PHP 字符串转换为 MySQL 时间戳值

database - 支持多个并发用户的文件数据库建议

database - 使用 powerbi 在单个 dateTime 过滤器上过滤多个表

ruby-on-rails - 无法在 Rails 中使用 ActiveRecord 和 PostgreSQL 从每个组中选择不同的行

mysql - 如何在数据库中存储具有动态数量属性的数据