¿
美麗的API都是帶刺的玫瑰
1. toLocaleString相關背景
掘金 - 想偷懶的話,toLocaleString 瞭解一下?
MDN - Date.prototype.toLocaleString()
MDN - Number.prototype.toLocaleString()
其實就是在說: 這個API可以省很多事兒, 方便的對時間/數字按照一定格式進行轉換, 不用你寫正則, 不用你拖庫
1.1 常用時間轉換
以常用時間格式: YYYY-MM-DD HH:mm:ss
為例, 通常用庫day.js
或者moment.js
來完成
format('YYYY-MM-DD HH:mm:ss')
複製程式碼
使用toLocaleString
的話
new Date()
.toLocaleString('zh', { hour12: false }) // "2019/4/21 13:00:09"
.replace(/\//g, '-') // "2019-4-21 13:00:23"
複製程式碼
1.2 常用數字轉換
例如: 整數部分每三位加一個逗號, 通常用正則完成
const number = 123456789
number.toString().replace(/\B(?=(\d{3})+\b)/g, ',') // "12,345,678"
複製程式碼
使用toLocaleString
的話
const number = 123456789
number.toLocaleString() // "12,345,678"
複製程式碼
2. 坑
上面的一切看著都很美好, 雖然它有瀏覽器相容問題, 但是我覺得在node.js
中使用的話, 應該是可以把這份美好延續下去的
但是在一次提交中, 升級了node
版本, 涉及到toLocaleString
的地方都出現了很多問題
FROM node:8.9-alpine
// 更改為
FROM node:lts-alpine
複製程式碼
打破了這份美好, 測試程式碼如下
// index.js
console.log("en: " + new Date().toLocaleString('en', { hour12: false }))
console.log("zh: " + new Date().toLocaleString('zh', { hour12: false }))
// Dockerfile
FROM node:8.9-alpine
COPY . /app
CMD ["node", "/app/index.js"]
複製程式碼
映象node:8.9-alpine
輸出
en: 4/21/2019, 06:42:03
zh: 2019-4-21 06:42:03 (預期)
複製程式碼
映象node:10.15-alpine
輸出
en: 4/21/2019, 06:43:13
zh: 4/21/2019, 06:43:13
複製程式碼
映象node:11.14-alpine
輸出
en: 4/21/2019, 06:43:59
zh: 4/21/2019, 06:43:59
複製程式碼
映象node:11.14
輸出
en: 4/21/2019, 06:46:54
zh: 4/21/2019, 06:46:54
複製程式碼
本地node.js 11.13
輸出, 怪不得本地除錯是好的....
en: 4/21/2019, 14:49:27
zh: 2019-4-21 14:49:27
複製程式碼
Chrome瀏覽器
en: 4/21/2019, 14:51:33
zh: 2019/4/21 14:51:33
複製程式碼
3. 具體原因: 國際化支援
Node.js / JavaScript
的許多功能是提供國際化支援的, 例如
-
String.prototype.normalize()
-
String.prototype.toLowerCase()
-
Date.prototype.toLocaleString()
-
require('buffer').transcode()
-
...略
Node.js
(及其底層V8引擎)使用ICU實現這些功能
但是要支援世界上所有的語言環境需要一份非常大的ICU資料檔案, 而大多數使用者僅會使用ICU功能的一小部分, 因此預設情況下Node.js僅提供完整ICU資料集的子集
3.1 構建Node.js的ICU選項
-
--with-intl=none/--without-intl
: 禁用所有國際化功能 -
--with-intl=system-icu
: 取決於系統, 大多數linux發行版都安裝了ICU -
--with-intl=small-icu
(預設): 完整ICU的一部分, 基本等價於: 僅限英文 -
--with-intl=full-icu
: 完整的支援
3.2 在執行時提供ICU資料
- npm模組: full-icu: 安裝完整的ICU資料
- 通過
npm i full-icu
, 資料檔案將會拷貝在./node_modules/full-icu
,
- 通過設定環境變數
NODE_ICU_DATA
指定執行時的ICU選項
env NODE_ICU_DATA=/some/directory node
3.3 測試
-
npm install full-icu
, 確保package.json
中有full-icu
-
編寫如下的Dockerfile
FROM node:lts-alpine
WORKDIR /app
COPY package.json /app
RUN yarn --registry=https://registry.npm.taobao.org
COPY . /app
ENV NODE_ICU_DATA /app/node_modules/full-icu
CMD ["node", "/app/index.js"]
複製程式碼
輸出
en: 4/21/2019, 09:13:13
zh: 2019/4/21 09:13:13
複製程式碼
雖然和預期2019-4-21 09:13:13
有點區別... 還是能說明有效吧- -
4. 小結
-
對於
toLocaleString
這個API, 瀏覽器環境下不相容問題更多, Node環境下也會出現不一致的問題, 但可以通過設定ICU來解決 -
從開發角度來說: API 雖然酷炫, 但是相比之下還是day.js / momemnt.js更穩定
-
涉及Node國際化支援的相關知識, 這部分可以參考官方文件Internationalization Support