Day.js 教程 - 轻量级的 JavaScript 日期处理库
项目概述
Day.js 是一个轻量级的 JavaScript 日期处理库,提供了与 Moment.js 相似的 API,但体积更小,性能更好。
- 项目链接:https://github.com/iamkun/dayjs
- 官方网站:https://day.js.org/
- GitHub Stars:46k+
核心功能
- 日期解析:解析各种格式的日期字符串
- 日期格式化:将日期格式化为各种字符串格式
- 日期操作:添加、减去时间单位
- 日期比较:比较两个日期的先后
- 国际化:支持多语言
- 插件系统:通过插件扩展功能
- 轻量级:体积小,压缩后仅 2KB
- API 与 Moment.js 兼容:与 Moment.js 的 API 相似,易于迁移
- 浏览器支持:支持所有现代浏览器
- Node.js 支持:支持 Node.js 环境
- TypeScript 支持:良好的 TypeScript 类型定义
安装与设置
基本安装
# 安装 Day.js
npm install dayjs
# 安装特定版本
npm install dayjs@1.11.10基本设置
// 导入 Day.js
import dayjs from 'dayjs';
// 或者使用 CommonJS 导入
const dayjs = require('dayjs');
// 导入插件
import relativeTime from 'dayjs/plugin/relativeTime';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import 'dayjs/locale/zh-cn'; // 导入中文语言包
// 使用插件
dayjs.extend(relativeTime);
dayjs.extend(localizedFormat);
// 设置默认语言
dayjs.locale('zh-cn');基本使用
创建日期对象
// 当前日期
dayjs();
// 特定日期
dayjs('2023-01-01');
dayjs('2023-01-01 12:00:00');
dayjs('2023-01-01T12:00:00Z');
// 时间戳
dayjs(1672531200000); // 毫秒时间戳
dayjs.unix(1672531200); // 秒时间戳
// 日期对象
dayjs(new Date());
// 复制日期对象
const date = dayjs();
const copy = dayjs(date);日期格式化
// 格式化日期
dayjs().format('YYYY-MM-DD'); // 2023-01-01
dayjs().format('YYYY-MM-DD HH:mm:ss'); // 2023-01-01 12:00:00
dayjs().format('YYYY年MM月DD日'); // 2023年01月01日
dayjs().format('HH:mm:ss'); // 12:00:00
// 使用本地化格式(需要 localizedFormat 插件)
dayjs().format('L'); // 01/01/2023
dayjs().format('LL'); // January 1, 2023
dayjs().format('LLL'); // January 1, 2023 12:00 PM
dayjs().format('LLLL'); // Sunday, January 1, 2023 12:00 PM
// 使用相对时间(需要 relativeTime 插件)
dayjs().fromNow(); // 2 hours ago
dayjs().toNow(); // in 2 hours
dayjs('2023-01-01').fromNow(); // 3 months ago日期操作
// 添加时间
dayjs().add(1, 'day'); // 明天
dayjs().add(1, 'week'); // 下周
dayjs().add(1, 'month'); // 下个月
dayjs().add(1, 'year'); // 明年
dayjs().add(1, 'hour'); // 1小时后
dayjs().add(1, 'minute'); // 1分钟后
dayjs().add(1, 'second'); // 1秒后
// 减去时间
dayjs().subtract(1, 'day'); // 昨天
dayjs().subtract(1, 'week'); // 上周
dayjs().subtract(1, 'month'); // 上个月
dayjs().subtract(1, 'year'); // 去年
// 设置时间
dayjs().set('year', 2023); // 设置年份为 2023
dayjs().set('month', 0); // 设置月份为 1 月(0-11)
dayjs().set('date', 1); // 设置日期为 1 号
dayjs().set('hour', 12); // 设置小时为 12
dayjs().set('minute', 0); // 设置分钟为 0
dayjs().set('second', 0); // 设置秒为 0日期比较
// 比较两个日期
const date1 = dayjs('2023-01-01');
const date2 = dayjs('2023-01-02');
// 是否在另一个日期之前
date1.isBefore(date2); // true
// 是否在另一个日期之后
date1.isAfter(date2); // false
// 是否与另一个日期相同
date1.isSame(date2); // false
// 是否与另一个日期相同或在其之前
date1.isSameOrBefore(date2); // true
// 是否与另一个日期相同或在其之后
date1.isSameOrAfter(date2); // false
// 比较单位
date1.isBefore(date2, 'year'); // false(年份相同)
date1.isBefore(date2, 'month'); // false(月份相同)
date1.isBefore(date2, 'date'); // true(日期不同)获取日期部分
// 获取年份
dayjs().year(); // 2023
// 获取月份(0-11)
dayjs().month(); // 0 表示 1 月
// 获取日期(1-31)
dayjs().date(); // 1
// 获取星期(0-6,0 表示星期日)
dayjs().day(); // 0
// 获取小时(0-23)
dayjs().hour(); // 12
// 获取分钟(0-59)
dayjs().minute(); // 0
// 获取秒(0-59)
dayjs().second(); // 0
// 获取毫秒(0-999)
dayjs().millisecond(); // 0高级特性
插件系统
Day.js 通过插件扩展功能,以下是一些常用插件:
常用插件
# 安装插件(如果使用 npm)
# 注意:Day.js 的插件通常包含在主包中,无需单独安装// 导入并使用插件
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime'; // 相对时间插件
import localizedFormat from 'dayjs/plugin/localizedFormat'; // 本地化格式插件
import isBetween from 'dayjs/plugin/isBetween'; // 检查日期是否在范围内
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; // 检查日期是否相同或在之前
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; // 检查日期是否相同或在之后
import customParseFormat from 'dayjs/plugin/customParseFormat'; // 自定义解析格式
import weekOfYear from 'dayjs/plugin/weekOfYear'; // 周数插件
import isoWeek from 'dayjs/plugin/isoWeek'; // ISO 周插件
import quarterOfYear from 'dayjs/plugin/quarterOfYear'; // 季度插件
// 使用插件
dayjs.extend(relativeTime);
dayjs.extend(localizedFormat);
dayjs.extend(isBetween);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
dayjs.extend(customParseFormat);
dayjs.extend(weekOfYear);
dayjs.extend(isoWeek);
dayjs.extend(quarterOfYear);使用相对时间插件
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);
// 相对时间
dayjs().fromNow(); // 2 hours ago
dayjs().toNow(); // in 2 hours
dayjs('2023-01-01').fromNow(); // 3 months ago
dayjs('2023-12-31').toNow(); // in 9 months
// 两个日期之间的相对时间
const date1 = dayjs('2023-01-01');
const date2 = dayjs('2023-01-02');
date1.from(date2); // 1 day ago
date1.to(date2); // in 1 day使用自定义解析格式插件
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);
// 解析自定义格式的日期字符串
const date = dayjs('2023-01-01 12:00:00', 'YYYY-MM-DD HH:mm:ss');
console.log(date.format('YYYY-MM-DD')); // 2023-01-01国际化
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn'; // 导入中文语言包
import 'dayjs/locale/en'; // 导入英文语言包
import 'dayjs/locale/ja'; // 导入日文语言包
// 设置全局语言
dayjs.locale('zh-cn');
console.log(dayjs().format('LLLL')); // 2023年1月1日星期日 12:00
// 临时使用其他语言
console.log(dayjs().locale('en').format('LLLL')); // Sunday, January 1, 2023 12:00 PM
console.log(dayjs().locale('ja').format('LLLL')); // 2023年1月1日日曜日 12:00日期范围
import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
dayjs.extend(isBetween);
// 检查日期是否在范围内
const date = dayjs('2023-01-15');
const start = dayjs('2023-01-01');
const end = dayjs('2023-01-31');
date.isBetween(start, end); // true
// 指定比较单位
date.isBetween(start, end, 'month'); // true日期克隆
// 克隆日期对象
const date1 = dayjs('2023-01-01');
const date2 = date1.clone();
date2.add(1, 'day');
console.log(date1.format('YYYY-MM-DD')); // 2023-01-01
console.log(date2.format('YYYY-MM-DD')); // 2023-01-02日期验证
// 验证日期是否有效
dayjs('2023-02-30').isValid(); // false(2月没有30天)
dayjs('2023-01-01').isValid(); // true
// 获取无效日期的原因
dayjs('2023-02-30').invalidReason(); // Invalid Date实用场景
日期格式化
import dayjs from 'dayjs';
// 格式化当前日期
console.log(dayjs().format('YYYY-MM-DD')); // 2023-01-01
console.log(dayjs().format('YYYY-MM-DD HH:mm:ss')); // 2023-01-01 12:00:00
console.log(dayjs().format('YYYY年MM月DD日')); // 2023年01月01日
console.log(dayjs().format('HH:mm:ss')); // 12:00:00
// 格式化特定日期
const date = dayjs('2023-01-01');
console.log(date.format('YYYY-MM-DD')); // 2023-01-01相对时间显示
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';
dayjs.extend(relativeTime);
dayjs.locale('zh-cn');
// 显示相对时间
console.log(dayjs().fromNow()); // 刚刚
console.log(dayjs().subtract(1, 'minute').fromNow()); // 1分钟前
console.log(dayjs().subtract(1, 'hour').fromNow()); // 1小时前
console.log(dayjs().subtract(1, 'day').fromNow()); // 1天前
console.log(dayjs().subtract(1, 'week').fromNow()); // 1周前
console.log(dayjs().subtract(1, 'month').fromNow()); // 1个月前
console.log(dayjs().subtract(1, 'year').fromNow()); // 1年前
// 显示未来相对时间
console.log(dayjs().add(1, 'minute').fromNow()); // 1分钟后
console.log(dayjs().add(1, 'hour').fromNow()); // 1小时后
console.log(dayjs().add(1, 'day').fromNow()); // 1天后日期计算
import dayjs from 'dayjs';
// 计算两个日期之间的差值
const date1 = dayjs('2023-01-01');
const date2 = dayjs('2023-01-02');
// 计算天数差
console.log(date2.diff(date1, 'day')); // 1
// 计算小时差
console.log(date2.diff(date1, 'hour')); // 24
// 计算分钟差
console.log(date2.diff(date1, 'minute')); // 1440
// 计算秒差
console.log(date2.diff(date1, 'second')); // 86400
// 计算月数差
const date3 = dayjs('2023-02-01');
console.log(date3.diff(date1, 'month')); // 1
// 计算年数差
const date4 = dayjs('2024-01-01');
console.log(date4.diff(date1, 'year')); // 1日期范围检查
import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
dayjs.extend(isBetween);
// 检查日期是否在范围内
function isDateInRange(date, startDate, endDate) {
return dayjs(date).isBetween(dayjs(startDate), dayjs(endDate), null, '[]');
// '[]' 表示包含开始和结束日期
}
console.log(isDateInRange('2023-01-15', '2023-01-01', '2023-01-31')); // true
console.log(isDateInRange('2023-02-01', '2023-01-01', '2023-01-31')); // false日期工具函数
import dayjs from 'dayjs';
// 获取当月第一天
function getFirstDayOfMonth(date) {
return dayjs(date).startOf('month').format('YYYY-MM-DD');
}
// 获取当月最后一天
function getLastDayOfMonth(date) {
return dayjs(date).endOf('month').format('YYYY-MM-DD');
}
// 获取当周第一天(星期日)
function getFirstDayOfWeek(date) {
return dayjs(date).startOf('week').format('YYYY-MM-DD');
}
// 获取当周最后一天(星期六)
function getLastDayOfWeek(date) {
return dayjs(date).endOf('week').format('YYYY-MM-DD');
}
// 获取今年第一天
function getFirstDayOfYear(date) {
return dayjs(date).startOf('year').format('YYYY-MM-DD');
}
// 获取今年最后一天
function getLastDayOfYear(date) {
return dayjs(date).endOf('year').format('YYYY-MM-DD');
}
// 测试
console.log(getFirstDayOfMonth('2023-01-15')); // 2023-01-01
console.log(getLastDayOfMonth('2023-01-15')); // 2023-01-31
console.log(getFirstDayOfWeek('2023-01-15')); // 2023-01-15(假设 2023-01-15 是星期日)
console.log(getLastDayOfWeek('2023-01-15')); // 2023-01-21
console.log(getFirstDayOfYear('2023-01-15')); // 2023-01-01
console.log(getLastDayOfYear('2023-01-15')); // 2023-12-31最佳实践
- 导入必要的插件:只导入需要的插件,减少打包体积
- 使用链式调用:Day.js 支持链式调用,使代码更简洁
- 注意日期对象的不可变性:Day.js 的方法会返回新的日期对象,不会修改原对象
- 使用克隆:当需要基于现有日期进行操作时,使用 clone() 方法
- 设置默认语言:根据用户的语言环境设置默认语言
- 使用 TypeScript:使用 TypeScript 提供类型安全
- 测试:为日期处理逻辑编写测试
- 文档:为日期处理逻辑编写文档
- 与 Moment.js 迁移:如果从 Moment.js 迁移,注意 API 的细微差异
- 性能考虑:对于大量日期处理,注意性能优化
常见问题与解决方案
1. 日期解析失败
问题:解析特定格式的日期字符串失败
解决方案:
- 使用 customParseFormat 插件
- 确保日期字符串格式正确
- 检查是否需要指定格式
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);
// 解析自定义格式的日期字符串
const date = dayjs('01/01/2023', 'MM/DD/YYYY');
console.log(date.format('YYYY-MM-DD')); // 2023-01-012. 插件不工作
问题:导入的插件不工作
解决方案:
- 确保正确导入插件
- 确保使用 extend() 方法注册插件
- 检查插件名称是否正确
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
// 正确使用插件
dayjs.extend(relativeTime);
console.log(dayjs().fromNow()); // 现在可以正常工作3. 国际化不工作
问题:设置语言后,日期格式没有变化
解决方案:
- 确保正确导入语言包
- 确保使用 locale() 方法设置语言
- 检查语言包名称是否正确
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
// 正确设置语言
dayjs.locale('zh-cn');
console.log(dayjs().format('LLLL')); // 现在应该显示中文4. 日期计算错误
问题:日期计算结果不符合预期
解决方案:
- 检查日期对象是否正确创建
- 检查使用的时间单位是否正确
- 检查是否需要使用 clone() 方法
// 错误示例
const date = dayjs('2023-01-01');
date.add(1, 'day'); // 错误:没有赋值
console.log(date.format('YYYY-MM-DD')); // 2023-01-01
// 正确示例
const date = dayjs('2023-01-01');
const newDate = date.add(1, 'day'); // 正确:赋值给新变量
console.log(newDate.format('YYYY-MM-DD')); // 2023-01-025. 与 Moment.js 的差异
问题:从 Moment.js 迁移到 Day.js 后,某些代码不工作
解决方案:
- 查看 Day.js 官方文档中的迁移指南
- 注意 API 的细微差异
- 检查是否需要导入额外的插件
与其他日期处理库的比较
Day.js vs Moment.js
- 体积:Day.js 体积小(2KB),Moment.js 体积大(16KB+)
- API:两者 API 相似,易于迁移
- 性能:Day.js 性能更好
- 不可变性:Day.js 返回新的日期对象,Moment.js 修改原对象
- 插件系统:Day.js 使用插件扩展功能,Moment.js 内置更多功能
- 语言支持:两者都支持多语言
Day.js vs Date-fns
- API 风格:Day.js 使用链式调用,Date-fns 使用函数式风格
- 体积:两者都很小
- 功能:Date-fns 内置更多功能
- 不可变性:两者都返回新的日期对象
- 国际化:两者都支持多语言
Day.js vs 原生 Date 对象
- API 简洁性:Day.js API 更简洁易读
- 功能丰富度:Day.js 提供更多功能
- 浏览器兼容性:Day.js 处理了浏览器兼容性问题
- 性能:原生 Date 对象性能更好
- 体积:原生 Date 对象无额外体积
参考资源
- 官方文档:https://day.js.org/docs/en/installation/installation
- GitHub 仓库:https://github.com/iamkun/dayjs
- 插件列表:https://day.js.org/docs/en/plugin/plugin
- 语言包列表:https://day.js.org/docs/en/i18n/i18n
- 与 Moment.js 比较:https://day.js.org/docs/en/installation/installation#comparison
- TypeScript 支持:https://day.js.org/docs/en/installation/typescript