Skip to content

Day.js - 日期时间处理

Day.js 是一个轻量级的 JavaScript 日期库,仅 2KB 大小,API 设计与 Moment.js 相同,但更加轻量和现代化。

安装

bash
npm install dayjs
bash
pnpm add dayjs
bash
yarn add dayjs
bash
bun add dayjs

基础使用

引入和初始化

javascript
import dayjs from 'dayjs'

// 当前时间
const now = dayjs()

// 指定日期
const date = dayjs('2024-11-28')

// 时间戳
const fromTimestamp = dayjs(1701158400000)

// Date 对象
const fromDate = dayjs(new Date())

常用 API

格式化

javascript
import dayjs from 'dayjs'

const date = dayjs('2024-11-28 15:30:00')

// 常用格式
date.format('YYYY-MM-DD')           // 2024-11-28
date.format('YYYY-MM-DD HH:mm:ss')  // 2024-11-28 15:30:00
date.format('YYYY年MM月DD日')        // 2024年11月28日
date.format('MM/DD/YYYY')           // 11/28/2024
date.format('HH:mm:ss')             // 15:30:00

// 格式化标记
// YYYY - 四位年份
// MM   - 两位月份
// DD   - 两位日期
// HH   - 24小时制小时
// mm   - 分钟
// ss   - 秒
// SSS  - 毫秒

获取时间信息

javascript
const date = dayjs('2024-11-28 15:30:45')

date.year()        // 2024
date.month()       // 10 (0-11,0代表1月)
date.date()        // 28
date.day()         // 4 (0-6,0代表周日)
date.hour()        // 15
date.minute()      // 30
date.second()      // 45
date.millisecond() // 0

// 获取时间戳
date.valueOf()     // 1701158445000
date.unix()        // 1701158445 (秒级时间戳)

设置时间

javascript
const date = dayjs('2024-11-28')

// 设置年份
date.year(2025)

// 设置月份 (0-11)
date.month(0)  // 1月

// 设置日期
date.date(15)

// 设置小时
date.hour(10)

// 设置分钟
date.minute(30)

// 链式调用
dayjs().year(2025).month(0).date(1).hour(0).minute(0).second(0)

时间操作

javascript
const date = dayjs('2024-11-28')

// 增加时间
date.add(1, 'day')      // 增加1天
date.add(1, 'month')    // 增加1个月
date.add(1, 'year')     // 增加1年
date.add(2, 'hour')     // 增加2小时
date.add(30, 'minute')  // 增加30分钟

// 减少时间
date.subtract(1, 'day')    // 减少1天
date.subtract(1, 'month')  // 减少1个月
date.subtract(1, 'year')   // 减少1年

// 支持的单位
// year, month, week, day, hour, minute, second, millisecond

开始和结束时间

javascript
const date = dayjs('2024-11-28 15:30:45')

// 一天的开始
date.startOf('day')    // 2024-11-28 00:00:00

// 一天的结束
date.endOf('day')      // 2024-11-28 23:59:59

// 月初
date.startOf('month')  // 2024-11-01 00:00:00

// 月末
date.endOf('month')    // 2024-11-30 23:59:59

// 年初
date.startOf('year')   // 2024-01-01 00:00:00

// 年末
date.endOf('year')     // 2024-12-31 23:59:59

// 周初 (周日)
date.startOf('week')   // 2024-11-24 00:00:00

// 周末 (周六)
date.endOf('week')     // 2024-11-30 23:59:59

时间比较

javascript
const date1 = dayjs('2024-11-28')
const date2 = dayjs('2024-11-30')

// 是否之前
date1.isBefore(date2)  // true

// 是否之后
date1.isAfter(date2)   // false

// 是否相同
date1.isSame(date2)    // false

// 指定粒度比较
date1.isSame(date2, 'month')  // true
date1.isSame(date2, 'year')   // true
date1.isSame(date2, 'day')    // false

时间差

javascript
const date1 = dayjs('2024-11-28')
const date2 = dayjs('2024-12-01')

// 相差天数
date2.diff(date1, 'day')     // 3

// 相差小时
date2.diff(date1, 'hour')    // 72

// 相差分钟
date2.diff(date1, 'minute')  // 4320

// 相差月份
date2.diff(date1, 'month')   // 0

// 支持小数
date2.diff(date1, 'month', true)  // 0.1

常用插件

相对时间 (RelativeTime)

javascript
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/zh-cn'

dayjs.extend(relativeTime)
dayjs.locale('zh-cn')

const date = dayjs('2024-11-25')

dayjs().to(date)        // 3天前
dayjs().from(date)      // 3天后
date.fromNow()          // 3天前
date.toNow()            // 3天后

自定义解析格式 (CustomParseFormat)

javascript
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'

dayjs.extend(customParseFormat)

// 解析自定义格式
dayjs('12-25-2024', 'MM-DD-YYYY')
dayjs('2024/11/28', 'YYYY/MM/DD')

是否为闰年 (IsLeapYear)

javascript
import dayjs from 'dayjs'
import isLeapYear from 'dayjs/plugin/isLeapYear'

dayjs.extend(isLeapYear)

dayjs('2024-01-01').isLeapYear()  // true
dayjs('2023-01-01').isLeapYear()  // false

周数 (WeekOfYear)

javascript
import dayjs from 'dayjs'
import weekOfYear from 'dayjs/plugin/weekOfYear'

dayjs.extend(weekOfYear)

dayjs('2024-11-28').week()  // 48 (一年中的第48周)

季度 (QuarterOfYear)

javascript
import dayjs from 'dayjs'
import quarterOfYear from 'dayjs/plugin/quarterOfYear'

dayjs.extend(quarterOfYear)

dayjs('2024-11-28').quarter()  // 4 (第四季度)

实际应用场景

场景1: 显示友好的时间格式

javascript
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/zh-cn'

dayjs.extend(relativeTime)
dayjs.locale('zh-cn')

function formatTime(timestamp) {
  const date = dayjs(timestamp)
  const now = dayjs()
  const diff = now.diff(date, 'day')
  
  if (diff === 0) {
    return date.format('HH:mm')  // 今天显示时间
  } else if (diff === 1) {
    return '昨天 ' + date.format('HH:mm')
  } else if (diff < 7) {
    return date.fromNow()  // 一周内显示相对时间
  } else {
    return date.format('YYYY-MM-DD')  // 更早显示日期
  }
}

// 使用
formatTime(Date.now())  // 15:30
formatTime(Date.now() - 86400000)  // 昨天 15:30
formatTime(Date.now() - 172800000)  // 2天前

场景2: 计算年龄

javascript
function calculateAge(birthday) {
  const birth = dayjs(birthday)
  const now = dayjs()
  
  return now.diff(birth, 'year')
}

calculateAge('1990-05-15')  // 34

场景3: 判断是否为工作日

javascript
function isWorkday(date) {
  const day = dayjs(date).day()
  return day !== 0 && day !== 6  // 0是周日,6是周六
}

isWorkday('2024-11-28')  // true (周四)
isWorkday('2024-11-30')  // false (周六)

场景4: 获取本月日期范围

javascript
function getMonthRange() {
  const start = dayjs().startOf('month')
  const end = dayjs().endOf('month')
  
  return {
    start: start.format('YYYY-MM-DD'),
    end: end.format('YYYY-MM-DD'),
    days: end.date()  // 本月天数
  }
}

getMonthRange()
// { start: '2024-11-01', end: '2024-11-30', days: 30 }

场景5: 倒计时

javascript
function countdown(targetDate) {
  const target = dayjs(targetDate)
  const now = dayjs()
  
  const days = target.diff(now, 'day')
  const hours = target.diff(now, 'hour') % 24
  const minutes = target.diff(now, 'minute') % 60
  const seconds = target.diff(now, 'second') % 60
  
  return {
    days,
    hours,
    minutes,
    seconds,
    total: target.diff(now, 'millisecond')
  }
}

countdown('2024-12-31 23:59:59')
// { days: 33, hours: 8, minutes: 29, seconds: 14, total: 2880554000 }

场景6: 日期范围选择器

javascript
function getDateRangePresets() {
  return {
    '今天': [
      dayjs().startOf('day'),
      dayjs().endOf('day')
    ],
    '昨天': [
      dayjs().subtract(1, 'day').startOf('day'),
      dayjs().subtract(1, 'day').endOf('day')
    ],
    '最近7天': [
      dayjs().subtract(6, 'day').startOf('day'),
      dayjs().endOf('day')
    ],
    '最近30天': [
      dayjs().subtract(29, 'day').startOf('day'),
      dayjs().endOf('day')
    ],
    '本月': [
      dayjs().startOf('month'),
      dayjs().endOf('month')
    ],
    '上月': [
      dayjs().subtract(1, 'month').startOf('month'),
      dayjs().subtract(1, 'month').endOf('month')
    ]
  }
}

场景7: 生成日历数据

javascript
function generateCalendar(year, month) {
  const firstDay = dayjs(`${year}-${month}-01`)
  const lastDay = firstDay.endOf('month')
  const daysInMonth = lastDay.date()
  
  const calendar = []
  
  for (let i = 1; i <= daysInMonth; i++) {
    const date = dayjs(`${year}-${month}-${i}`)
    calendar.push({
      date: i,
      day: date.day(),
      isWeekend: date.day() === 0 || date.day() === 6,
      isToday: date.isSame(dayjs(), 'day'),
      fullDate: date.format('YYYY-MM-DD')
    })
  }
  
  return calendar
}

generateCalendar(2024, 11)

场景8: 时区转换

javascript
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'

dayjs.extend(utc)
dayjs.extend(timezone)

// 转换到指定时区
const date = dayjs('2024-11-28 15:30:00')

date.tz('America/New_York').format('YYYY-MM-DD HH:mm:ss')
date.tz('Asia/Tokyo').format('YYYY-MM-DD HH:mm:ss')
date.tz('Europe/London').format('YYYY-MM-DD HH:mm:ss')

与 Moment.js 对比

特性Day.jsMoment.js
大小2KB67KB
API兼容 Moment.js-
不可变
维护状态活跃停止维护
性能更快较慢

最佳实践

  1. 按需引入插件: 只引入需要的插件,保持包体积最小
  2. 使用不可变操作: Day.js 默认不可变,每次操作返回新实例
  3. 统一时区处理: 在应用中统一使用 UTC 或指定时区
  4. 格式化缓存: 对于频繁使用的格式,可以提前定义常量
  5. 类型安全: 配合 TypeScript 使用,获得更好的类型提示

参考资源