Vue/JavaScript 日期时间格式化工具函数

一、代码

javascript 复制代码
/**
 * 日期时间格式化工具函数
 */

/**
 * 格式化日期
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {string} format - 格式化模板,默认 'YYYY-MM-DD'
 * @returns {string} 格式化后的日期字符串
 */
export function formatDate(date, format = 'YYYY-MM-DD') {
  if (!date) return ''
  
  const d = new Date(date)
  if (isNaN(d.getTime())) return ''
  
  const year = d.getFullYear()
  const month = d.getMonth() + 1
  const day = d.getDate()
  const hours = d.getHours()
  const minutes = d.getMinutes()
  const seconds = d.getSeconds()
  const milliseconds = d.getMilliseconds()
  
  const formatMap = {
    'YYYY': year,
    'YY': String(year).slice(-2),
    'MM': String(month).padStart(2, '0'),
    'M': month,
    'DD': String(day).padStart(2, '0'),
    'D': day,
    'HH': String(hours).padStart(2, '0'),
    'H': hours,
    'mm': String(minutes).padStart(2, '0'),
    'm': minutes,
    'ss': String(seconds).padStart(2, '0'),
    's': seconds,
    'fff': String(milliseconds).padStart(3, '0'),
    'ff': String(milliseconds).padStart(2, '0').slice(0, 2),
    'f': milliseconds
  }
  
  let result = format
  Object.keys(formatMap).forEach(key => {
    result = result.replace(new RegExp(key, 'g'), formatMap[key])
  })
  
  return result
}

/**
 * 格式化时间
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {boolean} includeSeconds - 是否包含秒数,默认 false
 * @returns {string} 格式化后的时间字符串
 */
export function formatTime(date, includeSeconds = false) {
  const format = includeSeconds ? 'HH:mm:ss' : 'HH:mm'
  return formatDate(date, format)
}

/**
 * 格式化日期时间
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {string} format - 格式化模板,默认 'YYYY-MM-DD HH:mm:ss'
 * @returns {string} 格式化后的日期时间字符串
 */
export function formatDateTime(date, format = 'YYYY-MM-DD HH:mm:ss') {
  return formatDate(date, format)
}

/**
 * 获取相对时间
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {Date|string|number} [baseDate] - 基准日期,默认为当前时间
 * @returns {string} 相对时间描述
 */
export function getRelativeTime(date, baseDate = new Date()) {
  const target = new Date(date)
  const base = new Date(baseDate)
  
  if (isNaN(target.getTime())) return ''
  
  const diff = base.getTime() - target.getTime()
  const absDiff = Math.abs(diff)
  const isFuture = diff < 0
  
  const minute = 60 * 1000
  const hour = 60 * minute
  const day = 24 * hour
  const week = 7 * day
  const month = 30 * day
  const year = 365 * day
  
  if (absDiff < minute) {
    return isFuture ? '刚刚' : '刚刚'
  } else if (absDiff < hour) {
    const minutes = Math.floor(absDiff / minute)
    return isFuture ? `${minutes}分钟后` : `${minutes}分钟前`
  } else if (absDiff < day) {
    const hours = Math.floor(absDiff / hour)
    return isFuture ? `${hours}小时后` : `${hours}小时前`
  } else if (absDiff < week) {
    const days = Math.floor(absDiff / day)
    return isFuture ? `${days}天后` : `${days}天前`
  } else if (absDiff < month) {
    const weeks = Math.floor(absDiff / week)
    return isFuture ? `${weeks}周后` : `${weeks}周前`
  } else if (absDiff < year) {
    const months = Math.floor(absDiff / month)
    return isFuture ? `${months}个月后` : `${months}个月前`
  } else {
    const years = Math.floor(absDiff / year)
    return isFuture ? `${years}年后` : `${years}年前`
  }
}

/**
 * 获取星期几
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {boolean} [short=false] - 是否使用简称
 * @returns {string} 星期几
 */
export function getWeekday(date, short = false) {
  const d = new Date(date)
  if (isNaN(d.getTime())) return ''
  
  const weekdays = short 
    ? ['日', '一', '二', '三', '四', '五', '六']
    : ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  
  return weekdays[d.getDay()]
}

/**
 * 判断是否为今天
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @returns {boolean} 是否为今天
 */
export function isToday(date) {
  const d = new Date(date)
  const today = new Date()
  
  return d.getDate() === today.getDate() &&
         d.getMonth() === today.getMonth() &&
         d.getFullYear() === today.getFullYear()
}

/**
 * 判断是否为昨天
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @returns {boolean} 是否为昨天
 */
export function isYesterday(date) {
  const d = new Date(date)
  const yesterday = new Date()
  yesterday.setDate(yesterday.getDate() - 1)
  
  return d.getDate() === yesterday.getDate() &&
         d.getMonth() === yesterday.getMonth() &&
         d.getFullYear() === yesterday.getFullYear()
}

/**
 * 判断是否为明天
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @returns {boolean} 是否为明天
 */
export function isTomorrow(date) {
  const d = new Date(date)
  const tomorrow = new Date()
  tomorrow.setDate(tomorrow.getDate() + 1)
  
  return d.getDate() === tomorrow.getDate() &&
         d.getMonth() === tomorrow.getMonth() &&
         d.getFullYear() === tomorrow.getFullYear()
}

/**
 * 获取日期范围描述
 * @param {Date|string|number} startDate - 开始日期
 * @param {Date|string|number} endDate - 结束日期
 * @returns {string} 日期范围描述
 */
export function getDateRange(startDate, endDate) {
  const start = new Date(startDate)
  const end = new Date(endDate)
  
  if (isNaN(start.getTime()) || isNaN(end.getTime())) return ''
  
  const startFormat = formatDate(start, 'MM-DD')
  const endFormat = formatDate(end, 'MM-DD')
  
  if (startFormat === endFormat) {
    return startFormat
  } else if (start.getFullYear() === end.getFullYear()) {
    return `${startFormat} ~ ${endFormat}`
  } else {
    return `${formatDate(start, 'YYYY-MM-DD')} ~ ${formatDate(end, 'YYYY-MM-DD')}`
  }
}

/**
 * 获取时间戳
 * @param {Date|string|number} [date] - 日期,默认为当前时间
 * @returns {number} 时间戳(毫秒)
 */
export function getTimestamp(date = new Date()) {
  return new Date(date).getTime()
}

/**
 * 时间戳转日期
 * @param {number} timestamp - 时间戳(毫秒)
 * @param {string} [format] - 格式化模板
 * @returns {string} 格式化后的日期字符串
 */
export function timestampToDate(timestamp, format = 'YYYY-MM-DD HH:mm:ss') {
  return formatDate(new Date(timestamp), format)
}

// 常用格式化模板
export const FORMAT_PATTERNS = {
  DATE: 'YYYY-MM-DD',
  TIME: 'HH:mm:ss',
  DATETIME: 'YYYY-MM-DD HH:mm:ss',
  DATETIME_SHORT: 'YYYY-MM-DD HH:mm',
  DATE_CN: 'YYYY年MM月DD日',
  DATETIME_CN: 'YYYY年MM月DD日 HH:mm:ss',
  MONTH: 'YYYY-MM',
  MONTH_CN: 'YYYY年MM月',
  YEAR: 'YYYY',
  YEAR_CN: 'YYYY年'
}

二、使用方式调用测试

1. 基本导入

javascript 复制代码
import { formatDate, formatTime, formatDateTime } from '@/utils/format.js'
import * as formatUtils from '@/utils/format.js'

2. formatDate() - 格式化日期

javascript 复制代码
formatDate(new Date())                    // '2025-01-19'
formatDate('2025-01-19')                  // '2025-01-19'
formatDate(1737264000000)                 // '2025-01-19'
formatDate(new Date(), 'YYYY年MM月DD日')  // '2025年01月19日'
formatDate(new Date(), 'YYYY/MM/DD')     // '2025/01/19'

3. formatTime() - 格式化时间

javascript 复制代码
formatTime(new Date())                    // '14:30'
formatTime(new Date(), true)              // '14:30:25'
formatTime('2025-01-19 14:30:25', true)   // '14:30:25'

4. formatDateTime() - 格式化日期时间

javascript 复制代码
formatDateTime(new Date())                // '2025-01-19 14:30:25'
formatDateTime(new Date(), 'YYYY/MM/DD HH:mm')  // '2025/01/19 14:30'

5. getRelativeTime() - 获取相对时间

javascript 复制代码
getRelativeTime(new Date(Date.now() - 1000 * 60))      // '1分钟前'
getRelativeTime(new Date(Date.now() - 1000 * 60 * 60)) // '1小时前'
getRelativeTime(new Date(Date.now() + 1000 * 60 * 30)) // '30分钟后'

6. getWeekday() - 获取星期几

javascript 复制代码
getWeekday(new Date('2025-01-19'))          // '星期日'
getWeekday(new Date('2025-01-20'))          // '星期一'
getWeekday(new Date('2025-01-19'), true)    // '日'

7. 日期判断函数

javascript 复制代码
isToday(new Date())                         // true
isYesterday(new Date(Date.now() - 86400000)) // true
isTomorrow(new Date(Date.now() + 86400000))  // true

8. getDateRange() - 获取日期范围

javascript 复制代码
getDateRange('2025-01-19', '2025-01-19')   // '01-19'
getDateRange('2025-01-15', '2025-01-19')   // '01-15 ~ 01-19'

9. getTimestamp() - 获取时间戳

javascript 复制代码
getTimestamp()                              // 1737264000000
getTimestamp('2025-01-19')                 // 1737264000000

10. timestampToDate() - 时间戳转日期

javascript 复制代码
timestampToDate(1737264000000)              // '2025-01-19 14:30:25'
timestampToDate(1737264000000, 'YYYY年MM月DD日')  // '2025年01月19日'

11. FORMAT_PATTERNS - 常用格式模板

javascript 复制代码
import { FORMAT_PATTERNS, formatDate } from '@/utils/format.js'

formatDate(new Date(), FORMAT_PATTERNS.DATE)        // '2025-01-19'
formatDate(new Date(), FORMAT_PATTERNS.DATE_CN)     // '2025年01月19日'
formatDate(new Date(), FORMAT_PATTERNS.DATETIME_CN) // '2025年01月19日 14:30:25'
formatDate(new Date(), FORMAT_PATTERNS.MONTH_CN)    // '2025年01月'

三、Vue 组件中使用示例

vue 复制代码
<template>
  <view class="container">
    <text>当前日期:{{ currentDate }}</text>
    <text>当前时间:{{ currentTime }}</text>
    <text>星期:{{ weekday }}</text>
    <text>相对时间:{{ relativeTime }}</text>
  </view>
</template>

<script>
import { 
  formatDate, 
  formatTime, 
  getWeekday, 
  getRelativeTime,
  FORMAT_PATTERNS 
} from '@/utils/format.js'

export default {
  data() {
    return {
      currentDate: '',
      currentTime: '',
      weekday: '',
      relativeTime: ''
    }
  },
  onLoad() {
    const now = new Date()
    this.currentDate = formatDate(now, FORMAT_PATTERNS.DATE_CN)
    this.currentTime = formatTime(now, true)
    this.weekday = getWeekday(now)
    this.relativeTime = getRelativeTime(new Date(Date.now() - 3600000))
  }
}
</script>

四、实际应用场景

场景1:打卡时间显示

javascript 复制代码
const signTime = '2025-01-19 08:45:30'
const displayTime = formatTime(signTime)  // '08:45'

场景2:消息列表相对时间

javascript 复制代码
const msgTime = new Date(Date.now() - 1800000) // 30分钟前
const displayTime = getRelativeTime(msgTime)    // '30分钟前'

场景3:日程日期范围

javascript 复制代码
const startDate = '2025-01-15'
const endDate = '2025-01-19'
const dateRange = getDateRange(startDate, endDate)  // '01-15 ~ 01-19'

五、支持的格式化占位符

占位符 说明 示例
YYYY 四位年份 2025
YY 两位年份 25
MM 两位月份(01-12) 01
M 月份(1-12) 1
DD 两位日期(01-31) 19
D 日期(1-31) 19
HH 两位小时(00-23) 14
H 小时(0-23) 14
mm 两位分钟(00-59) 30
m 分钟(0-59) 30
ss 两位秒数(00-59) 25
s 秒数(0-59) 25
fff 三位毫秒 123
ff 两位毫秒 12
f 毫秒 123
相关推荐
奔跑的web.2 小时前
TypeScript 泛型完全指南:写法、四大应用场景与高级用法
前端·javascript·vue.js·typescript
SevgiliD2 小时前
文本溢出省略并Tooltip组件在表单和表格内的使用
前端·javascript·vue.js
DEMO派2 小时前
Web 视频录制方案解析,轻松实现录屏!
前端·javascript·音视频
1024小神2 小时前
css主题theme变量切换实现原理学习记录
前端·css·学习
wuhen_n2 小时前
TypeScript工作流深度解析:从.ts到.js发生了什么?
前端·javascript·typescript
小二·2 小时前
Python Web 开发进阶实战:时空数据引擎 —— 在 Flask + Vue 中构建实时地理围栏与轨迹分析系统
前端·python·flask
Hao_Harrision2 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨ | TodoList(代办事项组件)
前端·typescript·react·tailwindcss·vite7
小二·2 小时前
Python Web 开发进阶实战:可验证网络 —— 在 Flask + Vue 中实现去中心化身份(DID)与零知识证明(ZKP)认证
前端·网络·python
运筹vivo@2 小时前
攻防世界:Web_php_include
前端·web安全·php