我用的是hive版本是3.1.3,spark版本是3.3.1,它們的unix_timestamp 函數在同樣的語句下轉換出來的時間戳是完全不同的,如下試驗所示
1.unix_timestamp 函數的坑
上圖試驗中我同樣的計算 2025-07-11 10:00:00 時間點對應的時間戳,但是盡管在我換了時區的情況下,他們得到的是同一個答案,都是 1752228000 ,沒錯,這個時間戳就是UTC+0時間下的對應2025-07-11 10:00:00的時間戳,這點就有點坑,因為我們變化了時區,肯定是想要它轉成對應時區下的時間戳。
在spark-sql中是會根據所給的時間戳改變的,這里有一個細節,特別需要注意,spark.sql.session.timeZone Zone一定要大寫,如果小寫的話,就會跟hive一樣達不到隨著時間戳改變而變化
2. 時間戳和對應時區的時間之間的轉換
首先需要明確的一點是時間戳的定義:它是指從自"Unix紀元"(1970-01-01 00:00:00 UTC)以來經過的秒數或毫秒數 所有它是一個絕對值,不會應為時區的變化而變化,而時區是指全球各個地區自己定義一天時間的方法。
基于上面對時間戳和時區概念的理解,我們提出一個結論,給定一個時間戳比如 1752163200 ,它是絕對的,也是不會變化的,根據這個時間戳,然后各地區根據自己所在的時區可以解析出不同的時間,比如,它表示 Asia/Shanghai(UTC+8) 時區的 2025-07-11 00:00:00 ,同時也表示Asia/Seoul(UTC+9) 時區的2025-07-11 01:00:00,同時也表示America/New_York(UTC-4)2025-07-10 12:00:00時區的等等
這是時間戳轉根據時區轉時間,我們可以明顯看出來在時間戳轉時間的時候,如果知道了一個轉的結果,比如知道 Asia/Shanghai(UTC+8) 轉出來的時間是 2025-07-11 00:00:00 ,那對應的 America/New_York(UTC-4) 的時間不用再用時間戳轉,直接用目標時區的值(-4)減去前面基礎時區的值(+8),得到-12(-4-8=-12),最后用基礎時間加上前面計算出來的值就可以了,也就是2025-07-11 00:00:00加上-12個小時也就是2025-07-10 12:00:00。
如果是時間轉時間戳的時候,就正好相反,用基礎時區的值減去目標時區的值(由于這是時間戳計算,最后需要進行6060處理),然后和對基礎時區轉出來的時間戳做加法(減出來是負數就是減)