日期和时间处理是开发中的常见需求。JavaScript 的 Date 对象提供了日期时间的基本操作能力。
🎯 创建日期#
当前时间#
// 创建当前日期时间const now = new Date()console.log(now) // Wed Jan 15 2025 10:30:00 GMT+0800
// 获取时间戳(毫秒)console.log(Date.now()) // 1736912400000console.log(now.getTime()) // 同上console.log(+now) // 同上(一元加号转数字)指定日期#
// 传入时间戳(毫秒)const date1 = new Date(1736912400000)
// 传入日期字符串const date2 = new Date('2025-01-15')const date3 = new Date('2025-01-15T10:30:00')const date4 = new Date('January 15, 2025 10:30:00')
// 传入年月日时分秒(月份从0开始!)const date5 = new Date(2025, 0, 15) // 2025年1月15日const date6 = new Date(2025, 0, 15, 10, 30, 0) // 带时分秒
// 🔶 注意:月份是 0-11,不是 1-12new Date(2025, 0, 1) // 1月1日new Date(2025, 11, 31) // 12月31日日期字符串格式#
// ISO 8601 格式(推荐)new Date('2025-01-15') // 解析为 UTC 时间new Date('2025-01-15T10:30:00') // 本地时间new Date('2025-01-15T10:30:00Z') // UTC 时间new Date('2025-01-15T10:30:00+08:00') // 带时区
// 其他格式(兼容性可能有问题)new Date('01/15/2025') // MM/DD/YYYYnew Date('Jan 15 2025')new Date('15 Jan 2025')
// 🔶 不同浏览器解析结果可能不同// 建议使用 ISO 格式或时间戳获取日期信息#
获取各部分#
const date = new Date('2025-01-15T10:30:45.123')
// 年月日date.getFullYear() // 2025date.getMonth() // 0(一月,范围 0-11)date.getDate() // 15(日期,范围 1-31)date.getDay() // 3(星期三,0=周日,1-6=周一到周六)
// 时分秒毫秒date.getHours() // 10date.getMinutes() // 30date.getSeconds() // 45date.getMilliseconds() // 123
// 时间戳date.getTime() // 毫秒时间戳date.valueOf() // 同 getTime()
// 时区偏移(分钟)date.getTimezoneOffset() // -480(东八区,即 -8 小时)UTC 时间#
const date = new Date('2025-01-15T10:30:00+08:00')
// 获取 UTC 时间(比北京时间早8小时)date.getUTCFullYear() // 2025date.getUTCMonth() // 0date.getUTCDate() // 15date.getUTCHours() // 2(10 - 8 = 2)date.getUTCMinutes() // 30date.getUTCSeconds() // 0设置日期#
设置各部分#
const date = new Date()
// 设置年月日date.setFullYear(2025)date.setMonth(11) // 12月date.setDate(25)
// 设置时分秒date.setHours(12)date.setMinutes(0)date.setSeconds(0)date.setMilliseconds(0)
// 设置时间戳date.setTime(1736912400000)
// 链式调用(每个方法返回时间戳)const timestamp = new Date().setFullYear(2025)// 返回的是时间戳,不是 Date 对象日期溢出自动修正#
// 日期会自动修正const date = new Date(2025, 0, 32) // 1月32日console.log(date) // 2月1日
// 利用这个特性获取月末function getLastDayOfMonth(year, month) { // 下个月的第0天 = 这个月的最后一天 return new Date(year, month + 1, 0).getDate()}
getLastDayOfMonth(2025, 0) // 31(1月)getLastDayOfMonth(2025, 1) // 28(2月,非闰年)getLastDayOfMonth(2024, 1) // 29(2月,闰年)日期格式化#
内置方法#
const date = new Date('2025-01-15T10:30:00')
// 转字符串date.toString()// 'Wed Jan 15 2025 10:30:00 GMT+0800 (中国标准时间)'
date.toDateString() // 'Wed Jan 15 2025'date.toTimeString() // '10:30:00 GMT+0800 (中国标准时间)'
date.toLocaleDateString() // '2025/1/15'date.toLocaleTimeString() // '10:30:00'date.toLocaleString() // '2025/1/15 10:30:00'
// ISO 格式date.toISOString() // '2025-01-15T02:30:00.000Z'(UTC)date.toJSON() // 同 toISOString()
// UTC 字符串date.toUTCString() // 'Wed, 15 Jan 2025 02:30:00 GMT'toLocaleString 选项#
const date = new Date('2025-01-15T10:30:00')
// 自定义格式date.toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long',})// '2025年1月15日星期三'
date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false,})// '10:30:00'
date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false,})// '2025/01/15 10:30'
// 不同地区date.toLocaleDateString('en-US') // '1/15/2025'date.toLocaleDateString('ja-JP') // '2025/1/15'date.toLocaleDateString('de-DE') // '15.1.2025'自定义格式化函数#
function formatDate(date, format) { const map = { YYYY: date.getFullYear(), MM: String(date.getMonth() + 1).padStart(2, '0'), DD: String(date.getDate()).padStart(2, '0'), HH: String(date.getHours()).padStart(2, '0'), mm: String(date.getMinutes()).padStart(2, '0'), ss: String(date.getSeconds()).padStart(2, '0'), }
return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (matched) => map[matched])}
const date = new Date('2025-01-15T10:30:45')formatDate(date, 'YYYY-MM-DD') // '2025-01-15'formatDate(date, 'YYYY/MM/DD HH:mm:ss') // '2025/01/15 10:30:45'formatDate(date, 'MM月DD日') // '01月15日'日期计算#
时间差#
const start = new Date('2025-01-01')const end = new Date('2025-01-15')
// 毫秒差const diffMs = end - start // 1209600000
// 转换为其他单位const diffSeconds = diffMs / 1000const diffMinutes = diffMs / (1000 * 60)const diffHours = diffMs / (1000 * 60 * 60)const diffDays = diffMs / (1000 * 60 * 60 * 24) // 14
// 计算年龄function getAge(birthday) { const today = new Date() const birth = new Date(birthday) let age = today.getFullYear() - birth.getFullYear() const monthDiff = today.getMonth() - birth.getMonth()
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) { age-- }
return age}
getAge('1990-05-20') // 34(假设今天是2025年1月)日期增减#
// 加减天数function addDays(date, days) { const result = new Date(date) result.setDate(result.getDate() + days) return result}
const date = new Date('2025-01-15')addDays(date, 7) // 2025-01-22addDays(date, -7) // 2025-01-08
// 加减月份function addMonths(date, months) { const result = new Date(date) result.setMonth(result.getMonth() + months) return result}
addMonths(date, 1) // 2025-02-15addMonths(date, -1) // 2024-12-15
// 通用函数function addTime(date, value, unit) { const result = new Date(date) switch (unit) { case 'year': result.setFullYear(result.getFullYear() + value) break case 'month': result.setMonth(result.getMonth() + value) break case 'day': result.setDate(result.getDate() + value) break case 'hour': result.setHours(result.getHours() + value) break case 'minute': result.setMinutes(result.getMinutes() + value) break } return result}日期比较#
const date1 = new Date('2025-01-15')const date2 = new Date('2025-01-20')
// 比较(转为时间戳)date1 < date2 // truedate1 > date2 // falsedate1.getTime() === date2.getTime() // false
// 判断是否同一天function isSameDay(d1, d2) { return ( d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate() )}
// 判断是否今天function isToday(date) { return isSameDay(date, new Date())}
// 判断是否闰年function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0}
isLeapYear(2024) // trueisLeapYear(2025) // false实用函数#
获取特定日期#
// 获取今天的开始和结束function getStartOfDay(date = new Date()) { const result = new Date(date) result.setHours(0, 0, 0, 0) return result}
function getEndOfDay(date = new Date()) { const result = new Date(date) result.setHours(23, 59, 59, 999) return result}
// 获取本周一function getMonday(date = new Date()) { const result = new Date(date) const day = result.getDay() const diff = day === 0 ? -6 : 1 - day result.setDate(result.getDate() + diff) return getStartOfDay(result)}
// 获取本月第一天和最后一天function getFirstDayOfMonth(date = new Date()) { return new Date(date.getFullYear(), date.getMonth(), 1)}
function getLastDayOfMonth(date = new Date()) { return new Date(date.getFullYear(), date.getMonth() + 1, 0)}
// 获取某月的天数function getDaysInMonth(year, month) { return new Date(year, month + 1, 0).getDate()}相对时间#
function timeAgo(date) { const now = new Date() const past = new Date(date) const diffMs = now - past const diffSeconds = Math.floor(diffMs / 1000) const diffMinutes = Math.floor(diffSeconds / 60) const diffHours = Math.floor(diffMinutes / 60) const diffDays = Math.floor(diffHours / 24) const diffMonths = Math.floor(diffDays / 30) const diffYears = Math.floor(diffDays / 365)
if (diffSeconds < 60) return '刚刚' if (diffMinutes < 60) return `${diffMinutes}分钟前` if (diffHours < 24) return `${diffHours}小时前` if (diffDays < 30) return `${diffDays}天前` if (diffMonths < 12) return `${diffMonths}个月前` return `${diffYears}年前`}
timeAgo(new Date(Date.now() - 1000 * 60 * 5)) // '5分钟前'timeAgo(new Date(Date.now() - 1000 * 60 * 60 * 3)) // '3小时前'倒计时#
function countdown(targetDate) { const now = new Date() const target = new Date(targetDate) const diff = target - now
if (diff <= 0) { return { days: 0, hours: 0, minutes: 0, seconds: 0 } }
return { days: Math.floor(diff / (1000 * 60 * 60 * 24)), hours: Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)), minutes: Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)), seconds: Math.floor((diff % (1000 * 60)) / 1000), }}
countdown('2025-02-01')// { days: 17, hours: 13, minutes: 29, seconds: 15 }注意事项#
月份从 0 开始#
// 🔶 最常见的错误new Date(2025, 1, 15) // 2月15日,不是1月15日!
// ✅ 正确写法new Date(2025, 0, 15) // 1月15日new Date('2025-01-15') // 使用字符串避免混淆时区问题#
// 字符串解析的时区差异new Date('2025-01-15') // UTC 时间new Date('2025-01-15T00:00:00') // 本地时间
// 建议:明确指定时区new Date('2025-01-15T00:00:00+08:00') // 明确北京时间Date 对象是可变的#
const date = new Date('2025-01-15')const copy = date // 🔶 这只是引用,不是复制!
copy.setDate(20)console.log(date.getDate()) // 20,原对象也被修改了
// ✅ 正确复制const realCopy = new Date(date)const realCopy2 = new Date(date.getTime())总结#
| 方法 | 说明 |
|---|---|
new Date() | 当前时间 |
Date.now() | 当前时间戳 |
getFullYear/Month/Date | 获取年/月/日 |
getHours/Minutes/Seconds | 获取时/分/秒 |
setFullYear/Month/Date | 设置年/月/日 |
toLocaleDateString | 本地化日期字符串 |
toISOString | ISO 格式字符串 |
getTime | 获取时间戳 |
核心要点:
- 月份从 0 开始(0=一月,11=十二月)
- 推荐使用 ISO 格式字符串创建日期
- Date 对象是可变的,需要注意复制
- 时区问题需要特别关注
- 复杂日期操作考虑使用 day.js 等库