简介
Day.js 是一个轻量级的 JavaScript 日期库,它提供了简单易用的 API 来处理日期和时间。以及更加轻量级,并且具有更快的性能。
安装
npm install dayjs
使用
import dayjs from "dayjs";
dayjs().format("YYYY-MM-DD HH:mm:ss");
经典场景
1. 获取当前时间
dayjs().format("YYYY-MM-DD HH:mm:ss");
2. 格式化时间
dayjs("2021-01-01").format("YYYY-MM-DD HH:mm:ss");
3. 解析时间
dayjs("2021-01-01 12:00:00", "YYYY-MM-DD HH:mm:ss");
4. 时间加减
dayjs().add(1, "day").format("YYYY-MM-DD HH:mm:ss");
dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm:ss");
5. 时间比较
dayjs("2021-01-01").isBefore("2021-01-02");
dayjs("2021-01-01").isAfter("2021-01-02");
dayjs("2021-01-01").isSame("2021-01-01");
6. 获取时间差
dayjs("2021-01-01").diff("2021-01-02", "day");
类型 | 说明 |
year | 年 |
quarter | 季度 |
month | 月 |
week | 周 |
day | 天 |
hour | 小时 |
minute | 分钟 |
second | 秒 |
millisecond | 毫秒 |
diff 默认返回是整数,如果需要返回小数,可以传入第三个参数:true|false。
7. 快速获取常用日期
# 前一天
dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm:ss");
# 后一天
dayjs().add(1, "day").format("YYYY-MM-DD HH:mm:ss");
# 前一周
dayjs().subtract(1, "week").format("YYYY-MM-DD HH:mm:ss");
# 后一周
dayjs().add(1, "week").format("YYYY-MM-DD HH:mm:ss");
# 前一月
dayjs().subtract(1, "month").format("YYYY-MM-DD HH:mm:ss");
# 后一月
dayjs().add(1, "month").format("YYYY-MM-DD HH:mm:ss");
# 前一季
dayjs().subtract(1, "quarter").format("YYYY-MM-DD HH:mm:ss");
# 后一季
dayjs().add(1, "quarter").format("YYYY-MM-DD HH:mm:ss");
# 前一年
dayjs().subtract(1, "year").format("YYYY-MM-DD HH:mm:ss");
# 后一年
dayjs().add(1, "year").format("YYYY-MM-DD HH:mm:ss");
8. 日期范围
import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
dayjs.extend(isBetween);
// 是否属于某个范围
dayjs("2021-01-01").isBetween("2021-01-01", "2021-01-02");
// 是否属于某个范围(包含边界)
// [ 包含开始日期,包含结束日期 ]
// ( 不包含开始日期,不包含结束日期 )
dayjs("2021-01-01").isBetween("2021-01-01", "2021-01-02", "day", "[)");
9. 倒计时实现
import { useState, useEffect, useCallback, useRef } from "react";
import dayjs from "dayjs";
import duration from "dayjs/plugin/duration";
dayjs.extend(duration);
/**
* 倒计时 Hook
* @param {number} targetTime - 目标时间戳(毫秒)
* @param {number} interval - 更新间隔(毫秒),默认 1000ms
* @returns {Object} 倒计时状态
* @returns {number} remainingTime - 剩余时间(毫秒)
* @returns {boolean} isFinished - 是否结束
* @returns {Object} formattedTime - 格式化后的时间对象
* @returns {Function} reset - 重置倒计时
*/
export default function useCountdown(targetTime, interval = 1000) {
const [remainingTime, setRemainingTime] = useState(0);
const [isFinished, setIsFinished] = useState(false);
const targetTimeRef = useRef(targetTime);
// 计算剩余时间
const calculateRemainingTime = useCallback(() => {
const now = dayjs();
const target = dayjs(targetTimeRef.current);
const diff = target.diff(now);
if (diff <= 0) {
setRemainingTime(0);
setIsFinished(true);
return;
}
setRemainingTime(diff);
setIsFinished(false);
}, []);
// 格式化时间
const formatTime = useCallback((time) => {
const duration = dayjs.duration(time);
return {
days: Math.floor(duration.asDays()),
hours: duration.hours(),
minutes: duration.minutes(),
seconds: duration.seconds(),
milliseconds: duration.milliseconds(),
};
}, []);
// 重置倒计时
const reset = useCallback(() => {
// 更新目标时间引用
targetTimeRef.current = dayjs().add(24, "hour").valueOf();
setIsFinished(false);
calculateRemainingTime();
}, [calculateRemainingTime]);
useEffect(() => {
// 初始化目标时间
targetTimeRef.current = targetTime;
// 初始化
calculateRemainingTime();
// 设置定时器
const timer = setInterval(() => {
calculateRemainingTime();
}, interval);
// 清理定时器
return () => clearInterval(timer);
}, [calculateRemainingTime, interval, targetTime]);
return {
remainingTime,
isFinished,
formattedTime: formatTime(remainingTime),
reset,
};
}
// hook使用
const { formattedTime, isFinished, reset } = useCountdown(targetTime);
10. 日历组件实现
import { useState, useMemo } from "react";
import dayjs from "dayjs";
import weekOfYear from "dayjs/plugin/weekOfYear";
import isoWeek from "dayjs/plugin/isoWeek";
dayjs.extend(weekOfYear);
dayjs.extend(isoWeek);
export default function Calendar() {
const [currentDate, setCurrentDate] = useState(dayjs());
const [selectedDate, setSelectedDate] = useState(dayjs());
// 生成日历数据
const calendarData = useMemo(() => {
const firstDayOfMonth = currentDate.startOf("month");
const lastDayOfMonth = currentDate.endOf("month");
const firstDayOfWeek = firstDayOfMonth.day();
const daysInMonth = lastDayOfMonth.date();
const daysInPrevMonth = firstDayOfMonth.subtract(1, "month").daysInMonth();
const days = [];
// 上个月的天数
for (let i = firstDayOfWeek - 1; i >= 0; i--) {
days.push({
date: firstDayOfMonth.subtract(i + 1, "day"),
isCurrentMonth: false,
});
}
// 当前月的天数
for (let i = 1; i <= daysInMonth; i++) {
days.push({
date: currentDate.date(i),
isCurrentMonth: true,
});
}
// 下个月的天数
const remainingDays = 42 - days.length; // 6行7列
for (let i = 1; i <= remainingDays; i++) {
days.push({
date: lastDayOfMonth.add(i, "day"),
isCurrentMonth: false,
});
}
return days;
}, [currentDate]);
// 切换月份
const changeMonth = (delta) => {
setCurrentDate(currentDate.add(delta, "month"));
};
// 切换年份
const changeYear = (delta) => {
setCurrentDate(currentDate.add(delta, "year"));
};
// 判断是否是今天
const isToday = (date) => {
return date.isSame(dayjs(), "day");
};
// 判断是否是选中日期
const isSelected = (date) => {
return date.isSame(selectedDate, "day");
};
return (
<div className="w-full max-w-md mx-auto bg-white rounded-lg shadow-lg p-4">
{/* 日历头部 */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-2">
<button
onClick={() => changeYear(-1)}
className="p-2 hover:bg-blue-50 rounded-full transition-colors"
>
{"<<"}
</button>
<button
onClick={() => changeMonth(-1)}
className="p-2 hover:bg-blue-50 rounded-full transition-colors"
>
{"<"}
</button>
</div>
<div className="text-lg font-semibold text-blue-600">
{currentDate.format("YYYY年 MM月")}
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => changeMonth(1)}
className="p-2 hover:bg-blue-50 rounded-full transition-colors"
>
{">"}
</button>
<button
onClick={() => changeYear(1)}
className="p-2 hover:bg-blue-50 rounded-full transition-colors"
>
{">>"}
</button>
</div>
</div>
{/* 星期标题 */}
<div className="grid grid-cols-7 gap-1 mb-2">
{["日", "一", "二", "三", "四", "五", "六"].map((day) => (
<div
key={day}
className="text-center text-sm font-medium text-blue-600 py-2"
>
{day}
</div>
))}
</div>
{/* 日历主体 */}
<div className="grid grid-cols-7 gap-1">
{calendarData.map(({ date, isCurrentMonth }, index) => (
<button
key={index}
onClick={() => setSelectedDate(date)}
className={`
aspect-square p-1 text-sm rounded-lg transition-colors
${
isCurrentMonth
? "hover:bg-blue-50"
: "text-gray-400 hover:bg-gray-50"
}
${isToday(date) ? "bg-blue-100" : ""}
${
isSelected(date)
? "bg-blue-500 text-white hover:bg-blue-600"
: ""
}
`}
>
{date.date()}
</button>
))}
</div>
</div>
);
}
11.国际化
import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
dayjs.locale("zh-cn");
dayjs().format("YYYY-MM-DD HH:mm:ss");