我厌倦了 JavaScript 的 Date API,于是我修复了它
Source: Dev.to
进入 WristWatch
WristWatch 是我对 JavaScript 日期问题的答案。它是一个体积小(不到 10 KB)且零依赖的库,以一种实际上有意义的方式(至少对我而言)包装了原生 Date API。
我不想构建像 Moment.js 那样的大型框架。我只想要一个能让我:
- 在不每次都查文档的情况下格式化日期
- 在不哭泣的情况下进行日期运算
- 在不需要 JavaScript 考古学博士学位的情况下记住函数名称
- 不会意外地修改日期导致一切崩溃
有趣的部分
合理的月份
原生 Date.getMonth() 返回 0‑11。在 WristWatch 中,月份是 1‑12,正如普通人所期望的那样:
const date = new WristWatch('2025-12-05');
date.getMonth(); // 12 (December, not 11!)
不烂的格式化
想要格式化日期?只要告诉它你想要的格式:
const now = WristWatch.now();
now.format('YYYY-MM-DD'); // "2025-12-06"
now.format('MMMM D, YYYY'); // "December 6, 2025"
now.toRelative(); // "just now"
不再需要把十几种方法串在一起,也不必引入整个格式化库。
实际可用的日期运算
给日期加天数应该很简单。在 WristWatch 中,确实如此:
const today = WristWatch.now();
const tomorrow = today.add(1, 'day');
const nextWeek = today.add(1, 'week');
const nextMonth = today.add(1, 'month');
所有操作都是不可变的,所以不会意外弄坏原始日期。它还能处理诸如“把一个月加到 1 月 31 日会怎样?”这类边缘情况(答案是得到 2 月 28 日,而不是 3 月 3 日)。
不需要思考的比较
需要检查某个日期是否在另一个日期之前?直接写:
if (tomorrow.isAfter(today)) {
console.log('Tomorrow is in the future!');
}
if (date.isBetween(start, end)) {
console.log('Date is in range!');
}
不需要时间戳相减,不用动脑算,只需直接比较。
技术细节
零依赖
WristWatch 完全没有依赖。它是对原生 Date API 的轻量包装,这意味着它快速、可靠,并且不会因为某个随机依赖被废弃而崩溃。
完全类型化
从头到尾使用 TypeScript 编写。每个函数、每个参数、所有内容都有类型。
可摇树优化
只导入你需要的部分。
// 方法链式风格
import { WristWatch } from '@lukelowers/wrist-watch';
const ww = WristWatch.now();
ww.add(1, 'day').format('YYYY-MM-DD');
// 函数式风格
import { now, format, add } from '@lukelowers/wrist-watch';
const date = now();
format(add(date.getDate(), 1, 'day'), 'YYYY-MM-DD');
与原始方案紧密相关
我并不想重新造轮子,而是想在其基础上迭代。WristWatch 是一个包装器,仍然让人想起旧的实现方式,但不会与更大的库竞争。
实际经过测试
使用 fast-check 的基于属性的测试确保一切正常。数百个随机测试用例会跑遍每个函数,代码对任何想进一步测试的人都是开放的。
实话实说
大家都会劝你别自己写日期库。“直接用 Moment!”他们说。“直接用 date‑fns!”他们说。
Moment 已经不再维护。date‑fns 很棒,但体积庞大。有时你只想要一个简单的、恰好满足需求且不必引入半个 npm 的东西。
WristWatch 并不想成为面面俱到的库。它想成为我希望存在的库:小巧、专注、使用起来真的愉快。
想试试吗?
npm install @lukelowers/wrist-watch
GitHub 仓库 包含完整文档和示例。如果发现问题或想添加功能,欢迎提交 PR。