2023年5月22日 星期一

AdonisJs時間戳怎麼老是早八小時

在AdonisJs裏面時間物件預設是使用luxon的DateTime,但使用上你會發現時間會跟現實差時區的八小時(小編人在台灣GM+8),解決辦法就是在環境變數上加上TZ變數(注意不是TimeZone),

// .env
TZ=Asia/Taipei

只需要這樣,程式碼跟設定都無需做任何改動,你就會發現created_at跟updated_at都回到正常時間了。
但是!沒錯別這麼快走,上面說到只有created_at跟updated_at,可能底層有針對這兩個變數做特別處理,所以會特別順利。
如果你有自行設置其他datetime欄位或timestamp欄位,例如小編昨天新增了一個sent_at欄位,結果就不會如預期,還是差八小時,那這問題到底在哪呢?
經過思考後我想起,在db的設置上似乎也有timezone的設置,雖然不知道有沒有關係但就姑且一試吧。

mysql: {
client: "mysql",
connection: {
host: Env.get("MYSQL_HOST"),
port: Env.get("MYSQL_PORT"),
user: Env.get("MYSQL_USER"),
password: Env.get("MYSQL_PASSWORD", ""),
database: Env.get("MYSQL_DB_NAME"),
        // 加入 timezone,取自.env TZ
timezone: Env.get("TZ"),
},
// ...略
},

再來測試一下,竟然過了!太棒了下班!這幾天遇到的雷都還不算很大啊~

AdonisJs報錯Incorrect string value: '\xF0\xA6\x9F\x8C,\xE9...' for column 'table' at row 1

小編在進行文字儲存時,透過orm進行操作,最終指令如下

insert into goal_details
(created_at, domain_code, goal_id, is_achieved, level, reason, remark,
smart_goals,
sub_domain_code, updated_at)
values
('2023-05-22 15:18:38', 'DOMAINS.NUTRITION', 103, false, 1, NULL, NULL,
'如工作時外出午餐, 會到粉麵店叫低脂肉(牛筋, 牛𦟌,魚旦)+米粉/米線',
'SUB_DOMAINS.NUTRITION.REDUCE_FAT', '2023-05-22 15:18:38')

然後報錯:Incorrect string value:......

經過反覆測試發現問題在“𦟌”這個字上面,只要移除就沒事了。但想當然客戶不會接受這無理的需求,而且未來會不會有其他字無法存取不知道,所以只好再想辦法。

小編此時資料庫編碼為utf8mb4,理論上不應該呀,遵循chatGPT指示,嘗試把collation從utf8mb4_0900_ai_ci改成utf8mb4_unicode_520_ci,但問題還是沒有解決。

在苦無對策之際,我嘗試著把上面這句sql直接透過Navicat直接執行,竟然通過了!!所以問題並不在db,那就是在AdonisJs框架了,然後我想了一下,好像之前遇到要寫入表情符號時也遇過相同的錯誤訊息,最初db連線資訊預設是utf8mb3,那這樣似乎就說得通了,所以把config/database.ts的連線資訊加入charset,把它改成跟db一樣utf8mb4即可

mysql: {
client: 'mysql',
connection: {
host: Env.get('MYSQL_HOST'),
port: Env.get('MYSQL_PORT'),
user: Env.get('MYSQL_USER'),
password: Env.get('MYSQL_PASSWORD', ''),
database: Env.get('MYSQL_DB_NAME'),
        // 加入charset
charset: 'utf8mb4',
},
// ...略
},


再回去跑一下程式,發現過了。那就打完收工拉!!