在Web开发中,日期时间的处理需求几乎无处不在:页面上展示文章发布时间、订单系统计算过期时间、活动页面的倒计时效果,这些都依赖JavaScript提供的Date对象。不少初学者在使用Date对象时会被月份从0开始、时区偏移等问题搞得晕头转向,本文就来完整梳理Date对象的创建方式、常用方法以及典型实战场景,帮你把日期操作彻底搞明白。

Date对象的创建方式
创建Date对象只有一种正确途径:使用new关键字调用构造函数。直接调用Date()函数(不加new)得到的只是当前时间的字符串表示,而不是Date实例,这一点要特别注意。
Date构造函数支持四种参数形式。第一种是无参数,返回当前系统时间;第二种传入毫秒时间戳,得到该时间戳对应的日期对象;第三种是分别传入年、月、日、时、分、秒、毫秒,其中只有年和月是必填的,其余缺省为0;第四种是传入一个符合ISO 8601等标准的日期字符串。
// 方式一:无参数,获取当前时间
var now = new Date();
// 方式二:传入毫秒时间戳(从1970-01-01开始计算)
var d1 = new Date(1700000000000);
// 方式三:分别传入年月日时分秒
var d2 = new Date(2024, 0, 15); // 2024年1月15日,注意月份是0表示1月
var d3 = new Date(2024, 11, 25, 18, 30, 0); // 2024年12月25日18点30分
// 方式四:传入日期字符串
var d4 = new Date('2024-06-01T10:00:00');
var d5 = new Date('2024/06/01 10:00:00');这里有一个新手最容易踩的坑:使用数字参数时,月份范围是0到11,0代表一月,11代表十二月。所以new Date(2024, 0, 15)得到的是2024年1月15日而不是2月。而传日期字符串时又恢复了正常的1到12的月份习惯,两种方式规则不一致,务必记清楚。
另外,如果传入的日期字符串格式不合法,比如月份写成13月,构造出来的Date对象会是Invalid Date,后续任何方法调用都会返回NaN。因此在解析用户输入的日期前,一定要做合法性校验,可以用isNaN(d.getTime())来判断日期是否有效。
获取和设置时间的实例方法
Date原型上提供了一整套get系列方法用于读取时间字段,包括getFullYear()、getMonth()、getDate()、getDay()、getHours()、getMinutes()、getSeconds()和getMilliseconds()。这些方法分别返回年、月、日、星期、时、分、秒、毫秒。
需要特别区分两个容易混淆的方法:getDate()返回的是一个月中的第几天(1到31),而getDay()返回的是星期几(0到6,0代表星期日)。还有一个细节,getMonth()返回的月份同样从0开始,实际月份需要加1处理。
var d = new Date('2024-06-15T10:30:45');
console.log(d.getFullYear()); // 2024
console.log(d.getMonth()); // 5,实际是6月
console.log(d.getDate()); // 15
console.log(d.getDay()); // 6,星期六
console.log(d.getHours()); // 10
console.log(d.getMinutes()); // 30
console.log(d.getSeconds()); // 45与之对应的set系列方法用于修改时间字段,包括setFullYear()、setMonth()、setDate()、setHours()等。set方法一个非常实用的特性是自动进位:比如把日期设置为0,会自动回退到上个月最后一天;设置为32则会跳到下个月。利用这个特性可以优雅地计算上个月末的日期。
var d = new Date(2024, 5, 15); // 2024年6月15日 // setDate(0) 自动回退到上个月最后一天 d.setDate(0); console.log(d.getMonth(), d.getDate()); // 4 31,即5月31日 // setMonth会自动处理年份进位 d.setMonth(12); // 13月会进位到下一年1月
除了针对具体字段的方法,还有两个全局性的方法:getTime()返回毫秒时间戳,getTimezoneOffset()返回本地时区与UTC的分钟差,这两个方法在时间戳转换和时区计算中经常用到。
日期格式化与实战场景
Date自带的toLocaleString()、toLocaleDateString()、toLocaleTimeString()虽然能输出本地化格式,但往往满足不了产品设计的定制需求。实际项目中更常见的做法是自己封装一个格式化函数,把日期字段提取出来后按模板拼接。
// 通用的日期格式化函数
function formatDate(date, fmt) {
var o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 时
'm+': date.getMinutes(), // 分
's+': date.getSeconds() // 秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1,
RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
}
}
return fmt;
}
var d = new Date();
console.log(formatDate(d, 'yyyy-MM-dd hh:mm:ss')); // 2024-06-15 10:30:45
console.log(formatDate(d, 'yyyy/MM/dd')); // 2024/06/15日期加减也是高频需求。由于月份天数不固定,直接对数值做加减很容易出错,正确做法是借助set方法的自动进位特性,或者统一转换为毫秒再做运算。计算两个日期之间的差值时,先把两个日期都转成时间戳再相减,最后按需换算成天数、小时数即可。
// 日期加减:获取7天前的日期
function addDays(date, days) {
var d = new Date(date);
d.setDate(d.getDate() + days);
return d;
}
console.log(addDays(new Date(), -7));
// 计算两个日期相差的天数
function diffDays(start, end) {
var ms = end.getTime() - start.getTime();
return Math.floor(ms / (1000 * 60 * 60 * 24));
}
console.log(diffDays(new Date('2024-06-01'), new Date('2024-06-15'))); // 14关于时区还有一点值得提醒:getHours()等方法获取的是本地时区的时间,而getUTCHours()系列获取的是UTC时间。如果项目涉及跨时区展示,比如服务器存的是UTC时间、客户端按当地时区显示,就一定要分清这两组方法,避免出现时间差8小时的经典bug。此外,字符串'2024-06-01'会被解析为UTC零点,而'2024/06/01'则解析为本地零点,这两种写法在跨时区环境下可能相差一天,团队协作时最好统一日期格式规范。
总结一下,Date对象的核心就是get和set两大系列方法,配合时间戳转换基本能覆盖日常需求。如果项目对日期处理要求比较复杂,比如频繁的日期比较、区间计算、本地化输出,也可以考虑引入dayjs这类轻量库,它的API更直观,时区处理也更省心。不过理解原生Date的原理始终是基础,弄懂了它再去用任何日期库都会得心应手。
JavaScript日期操作Date对象日期格式化修改时间:2026-09-12 05:16:34