前端开发【工具函数】基于dayjs 封装的DateUtils工具函数,可以直接拿着使用

前端开发中,日期处理是高频需求,以下按「格式化、差值计算、范围判断、特殊日期、时区 / 时间戳转换」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 对应的扩展插件)

相关推荐
风止何安啊6 分钟前
🚦 前端并发请求 “交通管制”:别让你的接口堵成早高峰
前端·javascript·面试
J船长10 分钟前
扫盲烂笔头:A 记录、CNAME 的作用, Nginx的用途,为啥叫反向代理
前端
妙码生花16 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(二十六):icon 组件封装
前端·vue.js·typescript
李明卫杭州17 分钟前
Vue2 & Vue3 中 Router `props` 配置详解:彻底摆脱 `$route` 依赖
前端·vue.js·前端框架
掘金一周18 分钟前
裁员了,公司很爽快,赔偿一分没少 | 沸点周刊 7.8
前端·人工智能·后端
熊猫钓鱼>_>21 分钟前
2026 前端的三场底层革命:当 Vue、React Native 和 Three.js 同时去掉中间层
前端·javascript·vue.js·react native·架构·webgl·three.js
名字还没想好☜31 分钟前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
自己记录_理解更深刻1 小时前
Computed 聚合依赖+ 竞态处理
vue.js
宸翰1 小时前
uni-app 设置 Android 底部虚拟导航栏背景色
android·前端·uni-app
柒和远方2 小时前
LeetCode 4. 寻找两个正序数组的中位数 —— 二分划分的艺术
javascript·python·算法