由于世界各国家与地区所处经度不同,地方时也不同,因此会划分为不同的时区。本文将会为您介绍在Hologres中时区的相关信息。
时区介绍
为了克服时间上的混乱,正式的时区划分包括二十四个时区(东、西各十二个时区),其中英国(格林尼治天文台旧址)为中时区(零时区)、东1~12区(正数,+
),西1~12区(负数,-
)。每个时区横跨经度十五度,时间正好是一小时。在国际上有两种时区的表达,分别为GMT和UTC。
GMT 0:00
是指格林尼治标准时间,这是以英国格林尼治天文台观测结果得出的时间,这是英国格林尼治当地时间,这个地方的当地时间过去被当成世界标准时间。
UTC +00:00
是指协调世界时。因为地球自转越来越慢,每年都会比前一年多出零点几秒,每隔几年协调世界时组织都会给世界时加一秒,让基于原子钟的世界时和基于天文学(人类感知)的格林尼治标准时间相差不至于太大。并将得到的时间称为UTC,这是现在使用的世界标准时间。
协调世界时不与任何地区位置相关,也不代表此刻某地的时间,所以在说明某地时间时要加上时区。也就是说GMT并不等于UTC,而是等于
UTC+0
,即GMT = UTC+0
,只是格林尼治刚好在零时区上。+08
是指时区为东八区,比零时区快八个小时。
Hologres兼容PostgreSQL协议。PostgreSQL遵循POSIX时区规范,在使用GMT、UTC修改时区时,其偏移量符号与上述符号相反,即负号表示东时区。在Hologres中所有日期和时间都用全球统一时间UTC格式存储,所有Region默认是UTC-08
(中国东八区时间),比世界协调时间(UTC)和格林尼治时间(GMT)快八小时的时区。同时Hologres提供两种存储时间戳的数据类型:不带时区的TIMESTAMP和带时区的TIMESTAMPTZ。
带有时区的数据建议都使用TIMESTAMPTZ类型存储。
名称 | 说明 | 精度 | 数据显示示例 |
TIMESTAMP | 格式为 存储的数据与写入的数据一样,当修改了客户端的时区时,里面存储的数据的值不会改变,即客户端展示的是写入的原始数据,没有时区偏移。 | 微秒 | 2022-01-01 01:01:01.123456 |
TIMESTAMP WITH TIME ZONE(TIMESTAMPTZ) | 格式为 Hologres使用UTC时区的值来存储TIMESTAMPTZ数据。在向TIMESTAMPTZ字段插入值的时候, Hologres会自动将客户端时区的值转换成UTC时区,在展示查询结果的时候,根据客户端TimeZone配置参数声明的时区转换为客户端时间。 | 毫秒 | 2022-02-01 10:33:20.125+08 |
查看默认的时区
查看当前客户端的时区。
show timezone;
说明在Holoweb中执行的结果为实例的默认时区(PRC)对应东八区。
如果使用其他开发工具,查询结果不是默认时区,则说明更改过客户端时区配置。
通过查询系统表查看每个地区对应的时区。
在Postgres中通过系统表pg_timezone_names存储不同地区的默认时区信息,可以通过如下命令查询系统表查看每个地区对应的时区。
select * from pg_timezone_names;
系统表参数说明如下。
参数
类型
描述
name
text
时区名称。
abbrev
text
时区缩写。
utc_offset
interval
UTC偏移时区,正数(+)表示格林威治以东,负数(-)表示格林威治以西。
is_dst
boolean
如果当前正在观察夏令时,则为真(t),否则为否(f)。
修改客户端时区
Hologres中允许使用以下几种形式指定时区。
完整的时区名称:例如America/New_York。
UTC时区的偏移:例如-08:00:00或UTC-08表示东八区,由于遵循POSIX时区规范,在使用GMT或UTC表示时区时,其偏移量符号与上述符号相反,因此负号(-)表示东时区。
Hologres中的常用时区及其对应参数值如下所示。
地域 | 时区 | 完整时区名 | UTC时区的偏移 |
| 东八区 |
| UTC-08 |
日本(东京) | 东九区 | Asia/Tokyo | UTC-09 |
印度尼西亚(雅加达) | 东七区 | Asia/Jakarta | UTC-07 |
德国(法兰克福) | 东一区 | Europe/Berlin | UTC-01 |
美国(弗吉尼亚) | 西五区 |
| UTC+05 |
美国(硅谷) | 西八区 |
| UTC+08 |
修改客户端时区
Hologres的时区默认按照UTC存储,所有Region默认为
UTC-08
(中国东八区)。可以通过修改客户端时区参数达到客户端显示不同时区的目的。通过以下命令进行修改客户端显示时区。说明修改时区是修改客户端展示时区,并不是修改底层存储的真实时区信息。
Session级别
通过set命令可以在Session级别设置GUC参数。Session级别的参数只在当前Session生效,当连接断开之后将会失效,建议加在SQL前一起执行,使用方法如下。
--修改为加拿大/东部时区 set timezone ='Canada/Eastern'; --修改为西五区 set timezone ='05:30:00';
数据库级别
可以通过
alter database <db_name> set <value>;
命令来DB级别设置GUC参数。说明此命令执行完成后:
在整个数据库级别生效,设置完成后当前连接需要重新断开连接才能生效。
新建数据库不会生效,需要重新手动设置。
使用方法如下。
--DB级别修改时区为'UTC'零时区 alter database <db_name> set timezone = 'UTC-0'; --DB级别修改时区为'UTC'西五时区 alter database <db_name> set timezone = 'UTC+05';
不同数据源与Hologres的时间类型映射
不同数据源与Hologres有关时间的数据类型映射如下表,建议按照推荐映射关系进行映射,否则会出现数据不一致/时区偏差的情况。
数据源 | 数据源数据类型 | 源数据示例 | Hologres数据类型 | 映射Hologres数据示例 | 说明 |
MySQL | DATETIME | 2001-07-14 02:14:19 | TIMESTAMP | 2001-07-14 02:14:19 | MySQL的DATETIME存储的是没有时区的时间(可以理解为字符串的时间格式),取值范围为 数据存储时,会按照原始的时间格式存储,不进行任何转换,因此在Hologres中映射为TIMESTAMP类型。 |
TIMESTAMP | 2019-02-23 05:21:16 | TIMESTAMPTZ | 2019-02-23 05:21:16+08 | MySQL的TIMESTAMP默认是UTC时间,带时区,取值范围为 数据存储前会根据数据库软件设置的时区(默认随系统),将写入的时间数据转化为UTC时间后,再进行存储。因此在Hologres映射为TIMESTAMPTZ类型。 | |
MaxCompute | DATETIME | 2021-11-29 00:01:00 | TIMESTAMPTZ | 2021-11-29 00:01:00.000+08 | MaxCompute的DATETIME默认是UTC时间,取值范围为 |
TIMESTAMP | 2021-01-11 00:00:00.123456789 | TIMESTAMPTZ | 2021-01-11 00:00:00.123+08 | MaxCompute的TIMESTAMP默认是UTC时间,取值范围为 说明 说明:Hologres底层会将纳秒转换为毫秒,无需关心精度问题。 | |
Flink | TIMESTAMP | 2007-04-30 13:10:02.047 | TIMESTAMPTZ | 2007-04-30 13:10:02.047+08 | Flink的TIMESTAMP类型默认是UTC时间,精确到毫秒,因此在Hologres中映射为TIMESTAMPTZ类型。 |
DataHub | TIMESTAMP | 2020-03-05 10:10:00.123456+08 | TIMESTAMPTZ | 2020-03-05 10:10:00.123+08 | DataHub的TIMESTAMP精确到微秒,使用UTC时间,Hologres Connector在写入过程中会自动将数据时区变为零时区,因此在Hologres中映射为TIMESTAMPTZ类型。 |
常见问题
DataHub实时同步数据至Hologres,Hologres的字段类型为TIMESTAMP,DataHub字段类型为TIMESTAMP,写入后Hologres中时间比实际少八个小时。
可能原因:Hologres Connector在写入过程中,会自动将数据时区变为零时区。如果Hologres字段设置为TIMESTAMP,不会带时区,写入后还是零时区,因此会少八个小时。
解决方法:重新建表,将Hologres中的字段改成TIMESTAMPTZ。
DataHub实时同步数据至Hologres,Hologres的字段类型为TIMESTAMPTZ,Tableau展示的时候与Hologres的时间差八个小时。
可能原因:Tableau前端时区展示问题。
解决方法:HoloWeb的时区默认为UTC-08(东八区),可以通过HoloWeb查看是否符合真实数据,然后在Tableau建立连接的时候,可以在Initial SQL(初始 SQL)里修改时区,命令示例如下。
--修改为按照东八区显示 set timezone to 'Asia/Shanghai';
MySQL数据同步到Hologres后时间显示为什么会出现
+08
?可能原因:
+08
代表的是当前客户端展示的是东八区时区,并不是数据是东八区。解决方法:通过修改客户端时区为指定的时区。
JDBC里面如何设置时区?
JDBC的时区显示默认同JVM时区,如果需要修改JDBC的时区显示,需要连接JDBC后,执行以下SQL进行修改。
-- 修改为东七区 set timezone = '+07';