前端开发中,日期处理是高频需求,以下按「格式化、差值计算、范围判断、特殊日期、时区 / 时间戳转换」5 类核心场景,整理可直接复用的 JS 工具函数,覆盖绝大多数日期处理需求:
bash
import dayjs from 'dayjs'
/**
* 日期相关工具函数(基于 dayjs 库)
*/
export const DateUtils = {
/**
* 通用日期格式化(支持多种输入类型,自定义输出格式)
* @param {Number|String|Date} time - 输入时间(时间戳/字符串/Date对象)
* @param {String} format - 输出格式(默认:YYYY-MM-DD HH:mm:ss)
* @returns {String} 格式化后的日期
*/
formatDate(time, format = 'YYYY-MM-DD HH:mm:ss') {
if (!time) return '' // 空值返回空字符串,避免报错
return dayjs(time).format(format)
},
/**
* 快捷格式化:仅显示日期(YYYY-MM-DD)
* @param {Number|String|Date} time - 输入时间
* @returns {String} 格式化后的日期
*/
formatDateOnly(time) {
return this.formatDate(time, 'YYYY-MM-DD')
},
/**
* 快捷格式化:仅显示时间(HH:mm:ss)
* @param {Number|String|Date} time - 输入时间
* @returns {String} 格式化后的时间
*/
formatTimeOnly(time) {
return this.formatDate(time, 'HH:mm:ss')
},
/**
* 相对时间格式化(如"1小时前""3天后")
* @param {Number|String|Date} time - 输入时间(与当前时间对比)
* @returns {String} 相对时间描述
*/
formatRelativeTime(time) {
if (!time) return ''
// 配置相对时间语言(中文)
dayjs.locale('zh-cn')
return dayjs(time).fromNow()
},
/**
* 计算两个日期的差值(支持多种单位)
* @param {Number|String|Date} start - 开始时间
* @param {Number|String|Date} end - 结束时间(默认当前时间)
* @param {String} unit - 差值单位(year/month/day/hour/minute/second,默认day)
* @returns {Number} 差值(整数,向下取整)
*/
getDateDiff(start, end = dayjs(), unit = 'day') {
if (!start) return 0
const startDay = dayjs(start)
const endDay = dayjs(end)
// dayjs.diff 返回整数,单位由 unit 指定
return endDay.diff(startDay, unit)
},
/**
* 计算年龄(精确到年)
* @param {Number|String|Date} birthday - 出生日期
* @returns {Number} 年龄
*/
calculateAge(birthday) {
if (!birthday) return 0
// 计算当前日期与生日的年差,自动处理"未到生日"的情况
return dayjs().diff(dayjs(birthday), 'year')
},
/**
* 计算两个时间的时长(格式:HH:mm:ss)
* @param {Number|String|Date} start - 开始时间
* @param {Number|String|Date} end - 结束时间
* @returns {String} 时长(如"02:30:15")
*/
calculateDuration(start, end) {
if (!start || !end) return '00:00:00'
const diffMs = dayjs(end).diff(dayjs(start)) // 差值(毫秒)
// 转换为小时、分钟、秒
const hours = Math.floor(diffMs / (3600 * 1000))
.toString()
.padStart(2, '0')
const minutes = Math.floor((diffMs % (3600 * 1000)) / (60 * 1000))
.toString()
.padStart(2, '0')
const seconds = Math.floor((diffMs % (60 * 1000)) / 1000)
.toString()
.padStart(2, '0')
return `${hours}:${minutes}:${seconds}`
},
/**
* 获取指定日期的当天范围(00:00:00 ~ 23:59:59)
* @param {Number|String|Date} time - 输入时间(默认当前时间)
* @returns {Object} 当天范围(start-开始时间,end-结束时间,均为YYYY-MM-DD HH:mm:ss格式)
*/
getDayRange(time = dayjs()) {
const targetDay = dayjs(time)
return {
start: targetDay.startOf('day').format('YYYY-MM-DD HH:mm:ss'), // 当天0点
end: targetDay.endOf('day').format('YYYY-MM-DD HH:mm:ss'), // 当天23点59分59秒
}
},
/**
* 获取近N天的日期范围(如近7天:今天 ~ 7天前)
* @param {Number} days - 天数(默认7天)
* @returns {Object} 近N天范围(start-开始时间,end-结束时间)
*/
getRecentDaysRange(days = 7) {
const todayEnd = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss')
const recentStart = dayjs()
.subtract(days - 1, 'day')
.startOf('day')
.format('YYYY-MM-DD HH:mm:ss')
return {
start: recentStart,
end: todayEnd,
}
},
/**
* 获取指定日期的当月范围(月初 ~ 月末)
* @param {Number|String|Date} time - 输入时间(默认当前时间)
* @returns {Object} 当月范围(start-月初,end-月末)
*/
getMonthRange(time = dayjs()) {
const targetMonth = dayjs(time)
return {
start: targetMonth.startOf('month').format('YYYY-MM-DD HH:mm:ss'), // 月初0点
end: targetMonth.endOf('month').format('YYYY-MM-DD HH:mm:ss'), // 月末23点59分59秒
}
},
/**
* 获取指定日期的上月范围(上月初 ~ 上月末)
* @param {Number|String|Date} time - 输入时间(默认当前时间)
* @returns {Object} 上月范围(start-上月初,end-上月末)
*/
getLastMonthRange(time = dayjs()) {
const lastMonth = dayjs(time).subtract(1, 'month')
return {
start: lastMonth.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
end: lastMonth.endOf('month').format('YYYY-MM-DD HH:mm:ss'),
}
},
/**
* 判断日期是否为今天
* @param {Number|String|Date} time - 输入时间
* @returns {Boolean} 是否为今天
*/
isToday(time) {
if (!time) return false
return dayjs(time).isSame(dayjs(), 'day')
},
/**
* 判断日期是否为昨天
* @param {Number|String|Date} time - 输入时间
* @returns {Boolean} 是否为昨天
*/
isYesterday(time) {
if (!time) return false
return dayjs(time).isSame(dayjs().subtract(1, 'day'), 'day')
},
/**
* 判断日期是否为周末(周六/周日)
* @param {Number|String|Date} time - 输入时间
* @returns {Boolean} 是否为周末
*/
isWeekend(time) {
if (!time) return false
const day = dayjs(time).day() // day() 返回0(周日)~6(周六)
return day === 0 || day === 6
},
/**
* 判断日期是否在指定范围内(包含边界)
* @param {Number|String|Date} time - 目标日期
* @param {Number|String|Date} start - 范围开始时间
* @param {Number|String|Date} end - 范围结束时间
* @returns {Boolean} 是否在范围内
*/
isInDateRange(time, start, end) {
if (!time || !start || !end) return false
const target = dayjs(time)
// isSameOrAfter:目标 >= 开始;isSameOrBefore:目标 <= 结束
return target.isSameOrAfter(start, 'second') && target.isSameOrBefore(end, 'second')
},
/**
* UTC时间转指定时区时间(默认北京时间)
* @param {Number|String|Date} utcTime - UTC时间(如2025-09-16T02:54:15Z)
* @param {String} timezone - 目标时区(默认Asia/Shanghai,即北京时间)
* @param {String} format - 输出格式(默认YYYY-MM-DD HH:mm:ss)
* @returns {String} 转换后的时间
*/
utcToTimezone(utcTime, timezone = 'Asia/Shanghai', format = 'YYYY-MM-DD HH:mm:ss') {
if (!utcTime) return ''
// 先解析为UTC时间,再转为目标时区
return dayjs.utc(utcTime).tz(timezone).format(format)
},
/**
* 时间戳转日期(支持10位/13位时间戳)
* @param {Number|String} timestamp - 时间戳(10位秒级/13位毫秒级)
* @param {String} format - 输出格式(默认YYYY-MM-DD HH:mm:ss)
* @returns {String} 格式化后的日期
*/
timestampToDate(timestamp, format = 'YYYY-MM-DD HH:mm:ss') {
if (!timestamp) return ''
const numTs = Number(timestamp)
// 10位时间戳(秒)转13位(毫秒)
const msTs = numTs.toString().length === 10 ? numTs * 1000 : numTs
return dayjs(msTs).format(format)
},
/**
* 日期转时间戳(支持指定单位)
* @param {Number|String|Date} time - 输入时间
* @param {String} unit - 时间戳单位(second-10位,millisecond-13位,默认millisecond)
* @returns {Number} 时间戳
*/
dateToTimestamp(time, unit = 'millisecond') {
if (!time) return 0
const target = dayjs(time)
return unit === 'second' ? target.unix() : target.valueOf() // unix()返回10位,valueOf()返回13位
},
}
这些工具函数基于 dayjs 的强大能力,覆盖了前端系统开发中「表单校验、报表筛选、状态显示、后端对接」等核心场景,可直接复制到项目中使用,也可根据业务需求扩展(如添加「农历转换」「节假日判断」等函数,需配合 dayjs 对应的扩展插件)