由于世界各国家与地区所处经度不同,地方时也不同,因此会划分为不同的时区。本文将会为您介绍在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时区规范,在使用GMTUTC修改时区时,其偏移量符号与上述符号相反,即负号表示东时区。在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时区的偏移

  • 中国

  • 新加坡

  • 马来西亚(吉隆坡)

东八区

  • PRC

  • Asia/Shanghai

  • Asia/Singapore

  • Asia/Kuala_Lumpur

UTC-08

日本(东京)

东九区

Asia/Tokyo

UTC-09

印度尼西亚(雅加达)

东七区

Asia/Jakarta

UTC-07

德国(法兰克福)

东一区

Europe/Berlin

UTC-01

美国(弗吉尼亚)

西五区

  • US/Eastern

  • America/New_York

UTC+05

美国(硅谷)

西八区

  • US/Pacific

  • America/Los_Angeles

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存储的是没有时区的时间(可以理解为字符串的时间格式),取值范围为'1000-01-01 00:00:00' to '9999-12-31 23:59:59'

数据存储时,会按照原始的时间格式存储,不进行任何转换,因此在Hologres中映射为TIMESTAMP类型。

TIMESTAMP

2019-02-23 05:21:16

TIMESTAMPTZ

2019-02-23 05:21:16+08

MySQL的TIMESTAMP默认是UTC时间,带时区,取值范围为'1970-01-01 00:00:01' UTC to ‘2038-01-19 03:14:07' UTC

数据存储前会根据数据库软件设置的时区(默认随系统),将写入的时间数据转化为UTC时间后,再进行存储。因此在Hologres映射为TIMESTAMPTZ类型。

MaxCompute

DATETIME

2021-11-29 00:01:00

TIMESTAMPTZ

2021-11-29 00:01:00.000+08

MaxCompute的DATETIME默认是UTC时间,取值范围为‘0000-1-1’ to ‘9999-12-31’,精确到毫秒。因此在Hologres中映射为TIMESTAMPTZ类型。

TIMESTAMP

2021-01-11 00:00:00.123456789

TIMESTAMPTZ

2021-01-11 00:00:00.123+08

MaxCompute的TIMESTAMP默认是UTC时间,取值范围为'0000-01-01 00:00:00.000000000' to '9999-12-31 23.59:59.999999999',精确到纳秒。因此在Hologres中映射为TIMESTAMPTZ类型。

说明

说明: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';