由于世界各國家與地區所處經度不同,地方時也不同,因此會劃分為不同的時區。本文將會為您介紹在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';