很多人掉進了odoo的時間坑
? ?
odoo約定關于日期的數據,存放在數據庫時,以 utc0 時區也就是不帶時區 存放,應用程序讀取日期展示日期時, 轉換成用戶的時區展示。 用戶的時區通過context傳遞。
? ?
odoo本身能很好的處理 這, 例如 每個模型都自帶的 create_date / write_date
代碼
? ?
它在處理這些的時候,會 使用 utc-0 時區 存數據庫。
? ?
在 web client 以及 其他界面 展示這些日期 信息時, 能 根據用戶的 時區, 例如 上海時區 【東8區】
? ?
? ?
? ?
? ?
如果用戶的時區 切換到 其他, 例如 fiji [ utc-12 區] 與 上海時間 相差 4小時。
? ?
? ?
展示的時間 為 當地時間, 在上海時間基礎上 加 4小時, 所以是 5/13 01:46
? ?
? ?
而訂單存放數據庫的 時間是 utc-0
? ?
? ?
? ?
但是 某些應用 在往數據庫存 這些時間的時候, 有的沒有處理好。
例如,stock picking 的 字段 date_done是 分揀完成時的 日期, 分揀完成時讀取 系統時間,此時本應該轉換為 utc-0 并寫入數據庫 作為 date_done.. 的數據
? ?
但是 odoo sa的程序員在寫這個邏輯的時候,并沒有轉換為utc-0
代碼
self.write(cr, uid, [picking.id], {'date_done': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context)
? ?
time.strftime() 讀取odoo服務器的當前時間【帶時區】, 如果服務器運行在 utc-8 ,則數據庫存的日期也是 with utc-8, 也就是 下圖示的前 2筆交易[ id = 15, 16]
? ?
? ?
? ?
這樣, 當用戶從應用程序讀取改數據時, 在此數據基礎上 +時差, 變成了。
? ?
? ?
造成 時差 8 小時
? ?
? ?
原因是, odoo代碼里面的相關 日期處理是 不正確的, 沒有 遵循 在存數據前去掉 時區信息。
? ?
? ?
要解決這個問題, 2個 方式
? ?
1, 遵守約定,存數據庫時使用 utc-0
? ?
例如 stock 有問題部分的 代碼 修改, 已經提交 PR [ https://github.com/odoo/odoo/pull/12063 ]
? ?
@@ -506,7 +506,7 @@ def _quant_create(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_pa
'qty': float_round(qty, precision_rounding=rounding),
'cost': price_unit,
'history_ids': [(4, move.id)],
- 'in_date': datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ 'in_date': datetime.utcnow().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'company_id': move.company_id.id,
'lot_id': lot_id,
'owner_id': owner_id,
? ?
? ?
2, 使用workaround 解決此問題, 那就是 將 odoo 服務器的時區設置為 utc -0
? ?
使用 dpkg-reconfigure tzdata 設置 時區
? ?
? ?
設置為 utc-0 之后的 測試
? ?
? ?
服務器設置為 utc-0 之后, datetime.datetime.now() 和 datetime.datetime.utcnow() 以及 time 獲取的時間 都是 不帶時區信息, 這樣 就能 避免時差 問題。
? ?
? ?
odoo 的時差 坑
技術