在前端开发中,处理日期和时间是常见需求,但原生 JavaScript 的 Date
对象功能有限且 API 不够友好。Moment.js
和 Day.js
是两个流行的时间处理库,它们提供了简洁易用的 API 来简化日期操作。
1、Moment.js
Moment.js
是一个历史悠久的时间处理库,提供了全面的日期格式化、解析、计算和国际化支持。
优点:
- 支持日期计算、格式化、时区处理等几乎所有场景。
- 是通过链式调用实现复杂操作。
- 完善的国际化和本地化支持
- 社区成熟,文档完善,生态丰富。
缺点:
- 体积较大:约
67KB
,gzip
后约20KB+
,可能影响应用加载速度。 - 可变对象设计,容易产生引用问题,例如在同一个方法多次调用 moment 方法,会产生数据异常。
- 性能相对较差。
- 官方停止维护,进入维护模式。
Tree-shaking
支持不佳。
2、常见用法
// 引入 Moment.js
import moment from 'moment';
// 1. 获取当前时间
const now = moment();
// 2. 格式化日期
console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 2023-05-10 14:30:00
// 3. 日期计算
const tomorrow = now.add(1, 'days');
const lastWeek = now.subtract(1, 'weeks');
// 4. 相对时间
console.log(moment('2023-01-01').fromNow()); // 4个月前
// 5. 解析字符串为日期
const date = moment('2023-05-10', 'YYYY-MM-DD');
// 6. 时区处理(需额外加载 moment-timezone)
const laTime = moment.tz('2023-05-10 12:00', 'America/Los_Angeles');
3、Day.js
Day.js
是一个轻量级的时间处理库,设计灵感来自 Moment.js
,但体积更小,约 2KB
,性能更高。它的 API 与 Moment.js
兼容,适合现代前端项目,新项目推荐使用。
优点:
- 核心体积仅 2KB,适合对包大小敏感的项目。
- 不可变对象设计,避免了引用问题,所有操作返回新实例,避免副作用。
- API 兼容 Moment,几乎完全继承 Moment 的 API,迁移成本低。
- 支持
Tree-shaking
,按需加载。 - 性能优秀,现代化设计,活跃维护,持续更新。
- 按需加载插件,避免引入无用代码。
缺点:
- 功能相对 Moment 较少,需要使用插件引用。
- 国际化需要额外支持。
- 社区相对较新。
4、常见用法
// 引入 Day.js
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc'; // 按需加载插件
// 使用插件
dayjs.extend(utc);
// 1. 获取当前时间
const now = dayjs();
// 2. 格式化日期
console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 2023-05-10 14:30:00
// 3. 日期计算
const tomorrow = now.add(1, 'day');
const lastWeek = now.subtract(1, 'week');
// 4. 相对时间(需加载 relativeTime 插件)
console.log(dayjs('2023-01-01').fromNow()); // 4个月前
// 5. 解析字符串为日期
const date = dayjs('2023-05-10', 'YYYY-MM-DD');
// 6. 时区处理(需加载 utc 和 timezone 插件)
const laTime = dayjs.utc('2023-05-10 12:00').tz('America/Los_Angeles');
5、JS 原生 API
如果项目对体积要求极高且仅需简单功能,可使用原生 API。
优点:无需额外依赖,浏览器原生支持,性能最好,占用内存少,所有JS环境都支持。
缺点:
- API 设计不够直观,月份从 0 开始计算。
- 时区处理复杂,并且容易出错,日期计算和格式化功能有限。
- 可变对象,容易产生副作用。
6、常见方法
// 1. 格式化日期
const now = new Date();
console.log(`${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`);
// 2. 日期计算
const tomorrow = new Date(now);
tomorrow.setDate(now.getDate() + 1);
// 3. 相对时间(简单实现)
const getRelativeTime = (date) => {
const diff = (new Date() - date) / 1000;
if (diff < 60) return `${Math.floor(diff)}秒前`;
if (diff < 3600) return `${Math.floor(diff / 60)}分钟前`;
return `${Math.floor(diff / 3600)}小时前`;
};
7、对比与选择建议
特性 | 原生API | Moment.js | Day.js |
---|---|---|---|
体积 | 原生 | ~20KB+(gzip 后) | ~2KB(gzip 后) |
兼容性 | 跨浏览器有兼容问题 | 支持 IE8+ | 现代浏览器(IE 需 polyfill) |
API 设计 | 可变数据(可能有副作用) | 可变数据(可能有副作用) | 不可变数据(更安全) |
生态 | 使用比较复杂 | 插件丰富,社区成熟 | 插件逐渐完善 |
适用场景 | 对日期要求不高的场景 | 复杂项目、需兼容旧浏览器 | 对体积敏感的项目 |
选择建议:
- 新项目:优先使用
Day.js
,体积小且性能高。 - 遗留项目:若已使用
Moment.js
且功能稳定,可继续使用;若需优化体积,可考虑迁移到Day.js
。 - 国际化需求:两者均支持,但
Day.js
的国际化文件需单独引入。
总结:
Moment.js
适合功能全面、兼容性要求高的项目。Day.js
适合追求极致性能和体积的现代项目。- 原生 API 适合简单场景,避免引入额外依赖。