PostgreSQL时区、时间不一致、差8小时

文章目录

  • 标准时间
  • unix时间戳
  • 系统时间与pg时间不一致?
    • //查看pg的时区与时间
      postgres=# select now();
      now
    • //查看时区
      postgres=# show timezone;
      TimeZone
  • 修改pg时区
    • session级配置
    • 用户级配置
    • 数据库级配置
    • 全局配置(永久生效)
    • //修改完配置时重新加载
      [root@localhost ~]$ pg_ctl reload
      server signaled
      [root@localhost ~]$ psql
      postgres=# show time zone;
      TimeZone
  • pg时间戳数据类型
  • 时间函数
    • 日期转时间戳
    • 时间戳转日期

标准时间

标准时间格式即人一眼就能看懂的时间格式,比如:2017/11/28 15:00:00

unix时间戳

unix时间戳格式,就是从1970年1月1日0点0分0秒(UTC/GMT的午夜)开始计时,所经过的秒数。

系统时间与pg时间不一致?

主要原因:是主机和pg的时区配置不一致

//查看系统时间与时区
[root@localhost ~]# date
Mon May 25 10:59:51 CST 2020
[root@localhost ~]# date -R
Mon, 25 May 2020 11:00:22 +0800
//查看系统时区,待补充

//查看pg的时区与时间
postgres=# select now();
now

2020-05-25 13:54:30.800375+08
(1 row)

//查看时区
postgres=# show timezone;
TimeZone

PRC
(1 row)

修改pg时区

//视图pg_timezone_names保存了所有可供选择的时区
postgres=# select * from pg_timezone_names;

session级配置

//修改时区,注意此默认为session级别
postgres=# set time zone ‘PRC’;
SET

用户级配置

alter role rolname set timezone=‘UTC’;
或者
alter role all set timezone=‘UTC’;

数据库级配置

alter database dbname set timezone=‘UTC’;

全局配置(永久生效)

//查看配置文件中时区设置,要想永久生效,此时需要修改配置文件
[root@localhost ~]$ grep timezone postgresql.conf
log_timezone = ‘US/Pacific’
timezone = ‘US/Pacific’

//修改完配置时重新加载
[root@localhost ~]$ pg_ctl reload
server signaled
[root@localhost ~]$ psql
postgres=# show time zone;
TimeZone

PRC

pg时间戳数据类型

PostgreSQL 提供两种存储时间戳的数据类型: 不带时区的 TIMESTAMP 和带时区的 TIMESTAMPTZ。

TIMESTAMP 数据类型可以同时存储日期和时间,但它不存储时区。这意味着,当修改了数据库服务器所在的时区时,它里面存储的值不会改变。

TIMESTAMPTZ 数据类型在存储日期和时间的同时还能正确处理时区。PostgreSQL 使用 UTC 值来存储 TIMESTAMPTZ 数据。在向 TIMESTAMPTZ 字段插入值的时候,PostgreSQL 会自动将值转换成 UTC 值,并保存到表里。当从一个 TIMESTAMPTZ 字段查询数据的时候,PostgreSQL 会把存储在其中的 UTC 值转换成数据库服务器、用户或当前连接所在的时区。

TIMESTAMP 和 TIMESTAMPTZ 都使用8字节存储空间。

在使用TIMESTAMP保存时间时,标准时间格式转unix时间戳的时候一定要考虑时区问题,原因如下:
linux后台环境的时区是东八区,东八区的unix时间戳是从1970年1月1日8点0分0秒开始计算的,从postgresql中提取出标准时间(TIMESTAMP)转换为unix时间戳的时候,pg默认把这个标准时间是当做格林尼治时间处理的,格林尼治时间要比东八区时间慢8个小时,所以得到的时间会有8小时误差。

时间函数

日期转时间戳

1
select EXTRACT(epoch FROM CAST( '2018-03-08 00:00:00' AS TIMESTAMP))===>1520467200

时间戳转日期

to_timestamp(duble)
返回类型: timestamp;
描述: 把UNIX纪元时间戳转日期需要(注意时区)

1
2
3
4
postgres=# select to_timestamp(3600);
      to_timestamp      
------------------------
 1970-01-01 09:00:00+08

东八区的显示效果如上,可以看到to_timestamp是考虑时区计算的。

其他日期相关函数
date()函数
select date(‘2018-01-01 10:20:12’)====》2018-01-01

to_date()函数
select to_date(‘2018-03-12 18:47:35’,‘yyyy-MM-dd hh24:mi:ss’) ====>2018-03-12