大家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
前言
近年来,前端开发人员开始寻找 Moment.js的替代品,Moment.js 是最著名、最常用的 JavaScript 库之一。Moment.js尽管功能丰富,但存在几个严重影响应用程序性能的问题。 今天要介绍的主角是Day.js,它在 GitHub 上的star 已经超过了 date-fns(其中Day.js是42.2k,而date-fns是30.9k),值得一窥究竟。
1.Moment.js
1.1 什么是Moment.js
在介绍Day.js之前,先了解下Moment.js。Moment.js 是一个开源时间、日期 JavaScript 库。 它用于高效的处理、解析、验证和显示时间数据。 Moment.js 的一大优点是它可以在浏览器和 Node.js两种环境中运行,而且支持几乎所有的标准日期格式、标准时区、相对时间和区域设置。
Moment.js的最大特点是:
- 解析:可用于字符串、对象或数组解析
- 验证:可通过 isValid() 检查日期是否有效。
- 操作:Moment.js 提供了多种数据方法操作日期。例如: startoftime 和 endoftime、subtract、add、local 等。
- 显示:可以根据需要以不同格式显示日期。
- 国际化:日期和时间根据区域设置显示。
- 自定义:可以自定义创建的语言环境
1.2 Moment.js 的优点和缺点
Moment.js 优点
- 丰富、简单的API
- 多平台兼容性
- 高级日期/时间格式
- 显示本地化日期
Moment.js 缺点
- 不支持tree-shaking:导致巨大的包大小并导致性能问题
- 文件大小比较重:最小为 67.9Kb。
- 存在可变性问题并导致错误。
- 具有复杂的 OOP API(参考文末资料)。
2.Day.js
2.1 什么是Day.js?
Day.js 是 Moment.js 的压缩版,Day.js声称拥有与 Moment.js 相同的 API,并将其文件大小减少了 97%。 Moment.js 完整压缩后文件的大小为 67,9Kb,而 Day.js 压缩后文件只有 2Kb。 同时,Day.js也支持国际化、插件等Moment.js的几乎所有功能。
2.2 Day.js vs. Moment.js?
下图从文件大小 (gzip)、Tree-shaking、流行度、方法丰富性、模式(Pattern)、时区支持和语言环境等全方面比较 Moment.js 和 Day.js。
同时,从NPM的周下载数据来看,虽然Moment.js(22457954)周下载量仍然高于Day.js(12679197),但是Moment.js已经有明显的下降趋势,而Day.js则稳步上升。所以,有理由相信,随着大多数开发者转向Day.js,Day.js超越Moment.js只是时间问题。
3.Day.js和Moment.js使用对比
字符串+日期格式
在 String + Date 格式中,它返回使用给定格式字符串解析的日期对象。
// Moment.js代码
moment('10-06-1996', 'MM-DD-YYYY');
// 输出 => "1995-12-24T13:00:00.000Z"
// dayjs代码
dayjs('10-06-1996');
// 输出 => "1996-10-06T13:00:00.000Z"
字符串+时间格式
返回使用给定格式字符串从日期字符串解析的日期。对于 String + Time 格式,day.js 需要 customParseFormat 插件。
// Moment.js使用
moment('2019-10-06 4:30', 'YYYY-MM-DD HH:mm');
// 输出 => "2019-10-06T17:30:00.000Z"
// dayjs 需要安装customParseFormat插件
dayjs('2019-10-06 4:30', 'YYYY-MM-DD HH:mm');
// 输出 => "2019-10-06T17:30:00.000Z"
当在 dayjs 中使用 customParseFormat 插件时,应该在代码顶部添加以下代码片段。
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);
// 插件安装
字符串 + 格式 + 语言环境
在 String + Format + locale 格式中,它返回使用给定格式字符串、语言环境解析的日期。
// Moment.js使用
moment('2019 mars', 'YYYY MMM', 'fr');
// =>输出 "2019-02-29T13:00:00.000Z"
// dayjs需要customParseFormat插件
dayjs('2019 mars', 'YYYY MMM', 'fr');
// =>输出 "2019-02-29T13:00:00.000Z"
当在 dayjs 中使用 customParseFormat 插件时,应该在代码顶部添加以下代码片段。
import customParseFormat from 'dayjs/plugin/customParseFormat';
import 'dayjs/locale/fr';
// 插件安装
dayjs.extend(customParseFormat);
获取毫秒/秒/分/小时
使用以下这些函数来获取给定日期的毫秒/秒/分钟/小时。
// Moment.js使用
moment().seconds();
//输出 => 58
moment().hours();
// 输出 => 18
// dayjs
dayjs().second();
// 输出 => 58
dayjs().hour();
// 输出 => 18
在上述方法的性能测试中,Moment.js耗时1500.703ms,dayjs仅耗时494.234ms。 使用以下函数来设置给定日期的毫秒/秒/分钟/小时。
// Moment.js
moment().seconds(30);
// 输出 => "2019-10-06T09:12:30.695Z"
moment().hours(13);
// 输出 => "2019-10-06T03:12:49.695Z"
// dayjs
dayjs().set('second', 30);
// 输出 => "2019-10-06T09:12:30.695Z"
dayjs().set('hour', 13);
// 输出 => "2019-10-06T03:12:49.695Z"
上述方法的性能测试中,Moment.js耗时1689.744ms,day.js耗时2037.603ms。
给定日期的最大值和最小值
在库的第一行下方返回给定日期的最大值,库的第二行返回给定日期的最小值。
const array = [
new Date(1996, 10, 06),
new Date(1994, 6, 18),
new Date(1993, 5, 25),
new Date(1959, 10, 4),
];
// Moment.js
moment.max(array.map(a => moment(a)));
// 输出 => "1996-11-06T13:00:00.000Z"
moment.min(array.map(a => moment(a)));
// 输出 => "1959-11-04T13:00:00.000Z"
// dayjs 需要 minMax 插件
dayjs.max(array.map(a => dayjs(a)));
// 输出 => "1996-11-06T13:00:00.000Z"
dayjs.min(array.map(a => dayjs(a)));
// 输出 => "1959-11-04T13:00:00.000Z"
当在 dayjs 中使用 minMax 插件时,应该在代码顶部添加下面的代码片段。
import minMax from 'dayjs/plugin/minMax';
// 插件
dayjs.extend(minMax);
加减时间操作
下面写的第一行用于将指定的天数添加到给定的日期,第二行用于从给定的日期减去指定的天数。
// Moment.js
moment().add(7, 'days');
// 输出 => "2019-10-13T09:12:49.695Z"
moment().subtract(7, 'days');
// 输出 => "2019-09-29T09:12:49.695Z"
// dayjs
dayjs().add(7, 'day');
// 输出 => "2019-10-13T09:12:49.695Z"
dayjs().subtract(7, 'day');
// 输出 => "2019-09-29T09:12:49.695Z"
在add方法的性能测试中,Moment.js耗时1309.485ms,dayjs耗时1911.881ms。在减法的性能测试中,Moment.js 耗时 1278.384ms,dayjs 耗时 1772.593ms。
时间差
使用以下这些函数来获取给定日期之间的时间单位。
// Moment.js
moment([2019, 10, 04]).diff(moment([2019, 10, 06]));
// 输出 => -172800000
moment([2019, 10, 04]).diff(moment([2019, 10, 06]), 'days');
// 输出 => -2
// dayjs
dayjs('2019-10-04').diff(dayjs('2019-10-06'), 'milliseconds');
// 输出 => -172800000
dayjs('2019-10-04').diff(dayjs('2019-10-06'), 'days');
// 输出 => -2
isBefore
使用以下这些函数来检查日期是否早于另一个日期。
// Moment.js
moment(‘2019–10–04’).isBefore(‘2019–10–06’);
// 输出 => true
// dayjs
dayjs(‘2019–10–04’).isBefore(‘2019–10–06’);
// 输出 => true
isAfter
// Moment.js
moment(‘2019–10–06’).isAfter(‘2019–10–04’);
// 输出 => true
// dayjs
dayjs(‘2019–10–06’).isAfter(‘2019–10–04’);
// 输出 => true
3.本文总结
Moment.js 和 Day.js 在功能上是等效的,但是在性能上,Day.js 比 Moment.js 更好。 可以说 Day.js 是一个缩小版的 Moment.js。随着Moment.js官方宣布停止更新新特性,也不会就已有问题进行修复,大家都应该寻找其他的日期处理工具,比如Day.js,又或者是Date-fns等。文末的参考资料提供了大量优秀文档以供学习,如果有兴趣的读者可以自行阅读。
参考资料
https://www.npmjs.com/package/dayjs
https://github.com/date-fns/date-fns
https://ch-k.medium.com/replace-moment-js-with-day-js-74e54a545f96
https://github.com/moment/moment/blob/develop/src/test/moment/add_subtract.js#L244-L286
本文暂时没有评论,来添加一个吧(●'◡'●)