谨慎使用toLocaleString!!!

时间:2025-03-29 20:40:32

¿

美丽的API都是带刺的玫瑰

1. toLocaleString相关背景

掘金 - 想偷懒的话,toLocaleString 了解一下?

MDN - Date​.prototype​.toLocale​String()

MDN - Number​.prototype​.toLocale​String()

其实就是在说: 这个API可以省很多事儿, 方便的对时间/数字按照一定格式进行转换, 不用你写正则, 不用你拖库

1.1 常用时间转换

以常用时间格式: YYYY-MM-DD HH:mm:ss为例, 通常用库或者来完成

  1. format('YYYY-MM-DD HH:mm:ss')
  2. 复制代码

使用toLocaleString的话

  1. new Date()
  2. .toLocaleString('zh', { hour12: false }) // "2019/4/21 13:00:09"
  3. .replace(/\//g, '-') // "2019-4-21 13:00:23"
  4. 复制代码

1.2 常用数字转换

例如: 整数部分每三位加一个逗号, 通常用正则完成

  1. const number = 123456789
  2. ().replace(/\B(?=(\d{3})+\b)/g, ',') // "12,345,678"
  3. 复制代码

使用toLocaleString的话

  1. const number = 123456789
  2. () // "12,345,678"
  3. 复制代码

2. 坑

上面的一切看着都很美好, 虽然它有浏览器兼容问题, 但是我觉得在中使用的话, 应该是可以把这份美好延续下去的

但是在一次提交中, 升级了node版本, 涉及到toLocaleString的地方都出现了很多问题

  1. FROM node:8.9-alpine
  2. // 更改为
  3. FROM node:lts-alpine
  4. 复制代码

打破了这份美好, 测试代码如下

  1. //
  2. ("en: " + new Date().toLocaleString('en', { hour12: false }))
  3. ("zh: " + new Date().toLocaleString('zh', { hour12: false }))
  4. // Dockerfile
  5. FROM node:8.9-alpine
  6. COPY . /app
  7. CMD ["node", "/app/"]
  8. 复制代码

镜像node:8.9-alpine输出

  1. en: 4/21/2019, 06:42:03
  2. zh: 2019-4-21 06:42:03 (预期)
  3. 复制代码

镜像node:10.15-alpine输出

  1. en: 4/21/2019, 06:43:13
  2. zh: 4/21/2019, 06:43:13
  3. 复制代码

镜像node:11.14-alpine输出

  1. en: 4/21/2019, 06:43:59
  2. zh: 4/21/2019, 06:43:59
  3. 复制代码

镜像node:11.14输出

  1. en: 4/21/2019, 06:46:54
  2. zh: 4/21/2019, 06:46:54
  3. 复制代码

本地 11.13输出, 怪不得本地调试是好的....

  1. en: 4/21/2019, 14:49:27
  2. zh: 2019-4-21 14:49:27
  3. 复制代码

Chrome浏览器

  1. en: 4/21/2019, 14:51:33
  2. zh: 2019/4/21 14:51:33
  3. 复制代码

3. 具体原因: 国际化支持

/ JavaScript的许多功能是提供国际化支持的, 例如

  • ()

  • ()

  • ()

  • require('buffer').transcode()

  • ...略

(及其底层V8引擎)使用ICU实现这些功能

但是要支持世界上所有的语言环境需要一份非常大的ICU数据文件, 而大多数用户仅会使用ICU功能的一小部分, 因此默认情况下仅提供完整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数据

  1. npm模块: full-icu: 安装完整的ICU数据
  • 通过npm i full-icu, 数据文件将会拷贝在./node_modules/full-icu,
  1. 通过设置环境变量NODE_ICU_DATA指定运行时的ICU选项
  • env NODE_ICU_DATA=/some/directory node

3.3 测试

  • npm install full-icu, 确保中有full-icu

  • 编写如下的Dockerfile

  1. FROM node:lts-alpine
  2. WORKDIR /app
  3. COPY /app
  4. RUN yarn --registry=
  5. COPY . /app
  6. ENV NODE_ICU_DATA /app/node_modules/full-icu
  7. CMD ["node", "/app/"]
  8. 复制代码

输出

  1. en: 4/21/2019, 09:13:13
  2. zh: 2019/4/21 09:13:13
  3. 复制代码

虽然和预期2019-4-21 09:13:13有点区别... 还是能说明有效吧- -

4. 小结

  1. 对于toLocaleString这个API, 浏览器环境下不兼容问题更多, Node环境下也会出现不一致的问题, 但可以通过设置ICU来解决

  2. 从开发角度来说: API 虽然酷炫, 但是相比之下还是 / 更稳定

  3. 涉及Node国际化支持的相关知识, 这部分可以参考官方文档Internationalization Support