发布于 2026-01-06 8 阅读
0

再见了,Moment.js!

再见了,Moment.js!

2020 年 9 月 15 日,Moment.js 维护团队宣布,世界上最流行的 JavaScript 日期库之一已经停止维护。

它无需过多介绍:根据NPM 的数据,截至 2020 年 9 月,Moment.js 每周下载量超过1400 万次,并拥有超过 46000 个依赖的开源软件包。Moment.js 自 2011 年以来一直存在,但其开发者出于自身原因决定停止对其的积极支持,这些原因也包括不可变性和对“摇树优化”(tree shaking)的支持。

虽然没必要抱怨,但这的确是一个值得关注其替代方案的好理由。当然,我必须告诉你,你无需立即将所有项目都替换掉 Moment.js;如果你使用它的地方不多,可以升级,但既然现在你开始开发的项目都不应该再使用它了

这里对几个推荐作为可行替代方案的日期库进行了概述比较。我们将重点介绍 TypeScript,因为它是一种越来越流行的语言,被很多项目所使用(我的意思是,真的有很多项目都在使用 TypeScript)。


首先,让我们创建一个非常基础的 React 应用,这样我们就可以快速启动这个项目并立即看到成果:
yarn create react-app play-date --template typescript

Moment.js

让我们来看看Moment.js,看看开始使用它有多么简单(或者我应该说“曾经”有多么简单?)。

在任何项目中使用 Moment.js 之前,首先需要安装它:
npm i moment或者yarn add moment

然后将其导入组件,就大功告成了:
import moment from 'moment';

日期对象
const test1 = new Date('2018-01-16'); // Date

首先,我们需要进行转换:
const obj1 = moment(test1); // Moment
就是这样——简单明了!Moment.js 直接接收 Date 对象并将其转换为自己的对象,以便我们可以对其进行操作。

如果我们需要知道里面装的是哪一年的,那也很容易查到:
obj1.year(); // number

或者计算一下从那时到现在已经过去了多少天:
moment().diff(obj1, 'days'); // number

日期字符串
const test2 = '2016-07-20'; // string

转换字符串:
moment(test2); // Moment
Moment.js 接受字符串“原样”接收,因此您只需关注其格式即可。
虽然 Moment 没有限制字符串格式,但它可能无法识别某些乱码。

Day.js

接下来我们来看看 Moment 最接近的替代品——Day.js 如果你曾经使用过 Moment.js,那么用 Day.js 替换它应该非常容易,虽然两者并不完全相同,但仍然值得一试。

开始使用 Day.js,只需将其添加到您的项目中即可:
npm i dayjs或者yarn add dayjs

然后导入:
import dayjs from 'dayjs';

即使是那些之前从未听说过 Moment 的人,前面两行文字也应该会让你觉得似曾相识。没错,它的安装和导入过程看起来确实和 Moment 一模一样。

日期对象
const test1 = new Date('2018-01-16'); // Date

Day.js 可能无法完全替代 Moment.js,但它提供了非常相似的 API,并且使用了相同的概念,即将所有内容都转换为一个对象。

将其转换为:
const obj1 = dayjs(test1); // Dayjs

如果我们需要知道里面装的是哪一年的,那就直接查一下:
obj1.year(); // number

或者简单地计算一下从那时到现在已经过了多少天:
dayjs().diff(obj1, 'day'); // number

使用 Moment.js 的好处在于,你可以计算天数年数,也可以只计算年数——这完全没问题。Day.js 就做不到这一点,但另一方面,这也是拥有一个真正轻量级库所必须付出的代价。

日期字符串
const test2 = '2016-07-20'; // string

我们还需要进行转换。Day.js 和 Moment.js 都能解析任何符合 ISO 8601 格式的字符串。但如果要解析其他格式的字符串,则必须提供所需的格式:
dayjs(test2, 'YYYY-MM-DD'); // Dayjs

卢克森

下一位参赛者给我们一个微妙的暗示,它的核心维护者几乎与 Moment 的核心维护者相同。

按照常规步骤将Luxon添加到您的项目中:
npm i luxon或者yarn add luxon

先退后一步。还记得我们决定使用 TypeScript 吗?与其他库不同,Luxon 没有自带类型定义,所以当你尝试导入它时,你的现代 IDE 应该会报错。以下是添加 TypeScript 支持的方法:
npm i @types/luxon或者yarn add @types/luxon

然后您可以继续执行下一个常规步骤:
import { DateTime } from 'luxon';

日期对象
const test1 = new Date('2018-01-16'); // Date

如果您认为我们需要对日期进行封装(或转换)才能使用,那么您是对的:
const obj1 = DateTime.fromJSDate(test1); // DateTime
与 Moment.js 不同,Luxon 不会为您提供单一的“入口点”来完成此操作。请参考其指南或使用代码自动补全功能来解析您的日期。

获取年份值:
obj1.toFormat('yyyy'); // string

这里我们得到的是字符串结果,因为toFormat() 函数可以使用 token 参数返回几乎任何格式的结果。

计算自那时以来经过了多少天:
DateTime.fromJSDate(new Date()).diff(obj1, 'days').as('days'); // number
语法非常努力地想要模仿 Moment.js,但它比我个人喜欢的要长得多,而且它给出的结果非常不精确。

日期字符串
const test2 = '2016-07-20'; // string

我们还需要使用相应的方法进行转换。虽然如果这个字符串不是 ISO 8601 格式,我们也可以使用fromFormat() 函数,但现在我们先用fromISO() 函数:
DateTime.fromISO(test2); // DateTime

日期函数

要继续添加下一个库,我们需要像往常一样添加date-fns
npm i date-fns :或者yarn add date-fns

这里就出现了它的第一个缺点——你不能像导入 Moment.js 或 Luxon 那样导入 date-fns,date-fns 的每个函数都需要单独添加到 import 语句中,因此你无法使用代码自动补全功能。
你需要知道你需要哪个函数,或者参考它的指南来找到正确的函数:
import { differenceInDays, getYear } from 'date-fns';

日期对象
const test1 = new Date('2018-01-16'); // Date

这个库基于所谓的“辅助函数”,这些函数依赖于对原生 Date 对象的操作,这非常棒。因此,我们无需任何转换即可立即使用它!

让我们再花一年时间:
getYear(test1); // number

然后计算一下从那时起过了多少天:
differenceInDays(new Date(), test1); // number

日期字符串
const test2 = '2016-07-20'; // string

遗憾的是,date-fns 无法识别字符串格式,因此要解析它,我们必须显式地提供字符串格式,但如果你的项目文档齐全且一致,这就不重要了:
parse(test2, 'yyyy-MM-dd', new Date()); // Date


这里的所有代码示例都可以在 GitHub 上的 React 应用中找到。

我必须说明,这篇关于 Moment 可能替代方案的简要概述并非这些库的完整指南,也不是“我应该用什么来替代 Moment.js?”的完整列表。
如果您知道更好的工具,请在评论区分享给大家。

文章来源:https://dev.to/gin_mitch/farewell-moment-js-bd3