NocoBase 社群中有一類重複出現的錯誤回報,特別是在中文論壇:「我所有的時間都偏移了 8 小時」或「日期顯示成前一天」。中國是 UTC+8,因此偏移量就是 8 小時。我把自己的實例設定在 UTC+9,果然——偏移了 9 小時。不論你的偏移量是多少,偏移大小就是那個值。
這種模式強烈暗示這不是隨機損壞,而是一種機制。我在 PostgreSQL 與 MySQL 上分別架設 NocoBase 2.x,並測量實際儲存的內容以及它如何被重新解讀,直到找出具體答案。
測試環境: NocoBase 2.0.51 與 2.1.23(官方 Docker 映像)× PostgreSQL 16 與 MySQL 8.4。所有資料皆透過 REST API 寫入與讀取,伺服器時區則透過容器的
TZ環境變數控制。我刻意忽略瀏覽器端渲染——這裡討論的是伺服器儲存的內容以及如何解讀。
背景:2.x 有四種日期時間欄位類型
NocoBase 2.x 的集合提供四種日期時間類型欄位(官方清單——雖然部分類型的詳細頁面仍標示「待補充」,這正是我選擇實際測量的原因):
| 類型 | 用途 |
|---|---|
| 含時區的日期時間 | 絕對瞬間——事件開始時間、紀錄檔 |
| 不含時區的日期時間 | 需要原樣保留的牆上時鐘時間 |
| 僅日期 | 生日、到期日、紀念日 |
| Unix 時間戳 | 系統整合 |
測量 1:各類型實際儲存的內容
我透過 xlsx 匯入「2026-07-12 09:00」,並查看每個資料庫中的原始值(2.0.51 與 2.1.23 結果相同):
| 欄位類型 | PostgreSQL | MySQL |
|---|---|---|
| 含時區的日期時間 |
timestamptz → 2026-07-12 09:00:00+09(包含偏移量的絕對瞬間) |
DATETIME → 2026-07-12 09:00:00(僅牆上時鐘——無偏移資訊) |
| 不含時區的日期時間 |
timestamp → 09:00:00
|
DATETIME → 09:00:00
|
| 僅日期 |
date → 2026-07-12
|
date → 2026-07-12
|
第一列就是關鍵。「含時區的日期時間」這個相同的欄位類型,在 PostgreSQL 中儲存為絕對瞬間,但在 MySQL 中則是純牆上時鐘值。MySQL 的 DATETIME 根本沒有地方存放偏移量。請記住這一點,後續實驗會用到。
測量 2:變更伺服器時區,儲存資料的意義也會改變(MySQL)
在 MySQL 環境中,我先以 TZ=UTC 寫入「2026-07-12 09:00」,再將應用程式容器改為 TZ=Asia/Tokyo 並重新啟動。其他什麼都沒動。
# MySQL 中的原始值(一個位元組都沒變)
dt_tz: 2026-07-12 09:00:00
# API 回傳的結果
TZ=UTC → "2026-07-12T09:00:00.000Z" (= UTC+9 的 18:00)
TZ=Asia/Tokyo → "2026-07-12T00:00:00.000Z" (= UTC+9 的 09:00)
進入全螢幕模式 離開全螢幕模式
磁碟上的資料完全相同,但作為絕對瞬間的意義卻偏移了 9 小時。因為 MySQL 的 DATETIME 沒有記錄「這是哪個時區的 09:00」,NocoBase 必須在每次讀寫時透過伺服器的 TZ 來解讀。之後再變更 TZ,資料庫中所有已儲存的日期時間意義就會同時改變。
這個機制解釋了大部分重複出現的「8 小時偏移」報告:實例一開始以 TZ 未設定(= UTC)啟動,後來有人設定為本地時間——或者測試與正式環境的 TZ 不一致。資料本身沒有損壞,只是解讀方式不同。
那 PostgreSQL 呢?我做了相同的實驗,數值完全沒有移動。 timestamptz 儲存了偏移量,因此沒有需要重新解讀的內容。
由此得出兩條規則:
-
第一天就選好伺服器
TZ並永遠不要再變更——特別是 MySQL。請在 compose 檔案中明確指定,並確保所有環境(開發、測試、正式)都一致。 - 如果可以選擇資料庫,PostgreSQL 在結構上就不會發生這類問題。
另一件事:匯入日期錯誤(確實存在,已修復)
並非所有日期偏移都是這個機制造成的。在 2.x 版本中也曾有真正的錯誤:在 v2.0.44–2.0.51 之間,CSV/Excel 匯入可能將日期儲存為前一天,即使資料庫、應用程式與伺服器時區都一致。這已被確認為缺陷,並於 2026 年 5 月中旬修復(論壇討論串 t/12426、t/12494)。
值得一提的是,我在 2.0.51 透過 API 匯入 xlsx/CSV 時無法重現此問題——兩個資料庫都能正確儲存日期。相關報告涉及 UI 路徑,因此可能是其他路由或環境因素所致。無論如何,目前版本已包含修復。
實務上的教訓是:當日期發生偏移時,請區分「這是機制造成的?」與「這是我目前版本的已知錯誤嗎?」了解測量 1 與 2 就能回答第一個問題;快速搜尋論壇(包含中文分類——這是最活躍的區域)則能回答第二個問題。
檢查清單
- 將欄位類型與意義配對。生日與到期日應使用「僅日期」。絕對瞬間應使用「含時區的日期時間」。將「含時區的日期時間」用在僅日期資料上,是導致日期顯示偏移一天的常見原因。
-
第一天就在 compose 檔案中固定伺服器
TZ,之後永遠不要再碰(特別是 MySQL)。UTC 或本地時區都可以;重點是選定一個並在所有環境中使用。 - 任何匯入後,開啟一筆紀錄檢查日期時間。這類偏移會影響每一列——檢查一筆紀錄就能了解全部。
- 如果發現異常:先檢查版本,再搜尋論壇——包含中文分類,大多數真實世界的報告都出現在那裡。
重點整理
- NocoBase 2.x 的「含時區的日期時間」在 PostgreSQL 中是絕對瞬間,但在 MySQL 中是牆上時鐘值 + 依
TZ解讀(實測結果)。 - 這就是為什麼之後變更伺服器
TZ會改變 MySQL 中所有已儲存日期時間的意義——這也是重複出現「8 小時偏移」(或 9 小時,或任何偏移量)的根源。 - 匯入日期偏移一天的錯誤確實存在,但已修復;請區分機制與已知錯誤,診斷就會更快。
(在 2.0.51 / 2.1.23 × PostgreSQL 16 / MySQL 8.4 上測量。未來版本的行為可能有所不同。)
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.