Node.js中Date对象设置日期显示值不符的原因及解决方法
嘿,我来帮你把这个日期问题掰扯清楚!你这段Node.js代码里的输出和预期不符,其实是两个容易踩的坑在搞怪:JavaScript Date的月份索引规则,还有时区转换的影响。
问题根源拆解
1. 月份参数是从0开始计数的!
这是JavaScript Date最容易让人踩坑的点之一:new Date(year, month, day)里的month参数是0索引的——0代表1月,1代表2月,一直到11代表12月。
你写的new Date(2017,01,01),其实是在创建2017年2月1日的日期,而不是你想要的1月1日!
2. 时区转换+日期自动修正的双重作用
再看第二个例子new Date(2017,01,31):2017年的2月只有28天,JavaScript会自动把无效的日期修正为有效日期——2月31日相当于2月28日再加3天,也就是2017年3月3日。
而你看到的输出是UTC格式的时间(末尾带Z),你的本地时区应该是UTC+5:30(比如印度时区),所以本地时间转UTC会减去5.5小时:
- 本地2017年2月1日00:00 → UTC 2017年1月31日18:30(对应你第一个输出)
- 本地2017年3月3日00:00 → UTC 2017年3月2日18:30(对应你第二个输出)
正确的传参方式
方式1:使用0索引的月份参数(最直接)
如果要创建2017年1月的日期,把月份参数改成0(代表1月)即可:
var date1 = new Date(2017, 0, 01); var date2 = new Date(2017, 0, 31); console.log("2017-01-01 is printed as ==>", date1); console.log("2017-01-31 is printed as ==>", date2);
以UTC+5:30时区为例,输出会是:
2017-01-01 is printed as ==> 2016-12-31T18:30:00.000Z
2017-01-31 is printed as ==> 2017-01-30T18:30:00.000Z
(这是本地时间转UTC后的结果,如果你想直接输出本地时间,可以用date1.toLocaleString()之类的方法)
方式2:使用ISO字符串(避免索引和时区混淆)
如果不想纠结月份索引,或者希望直接创建UTC时间的日期,用ISO格式的字符串传参是最省心的:
var date1 = new Date('2017-01-01'); var date2 = new Date('2017-01-31'); console.log("2017-01-01 is printed as ==>", date1); console.log("2017-01-31 is printed as ==>", date2);
这种方式下,new Date('YYYY-MM-DD')默认创建UTC时间的当天00:00,输出会完全符合预期:
2017-01-01 is printed as ==> 2017-01-01T00:00:00.000Z
2017-01-31 is printed as ==> 2017-01-31T00:00:00.000Z
方式3:明确指定本地时区
如果你需要确保创建的是本地时区的日期,也可以直接指定带时区的字符串:
// 创建UTC+5:30时区的2017年1月1日00:00 var date1 = new Date('2017-01-01T00:00:00+05:30'); var date2 = new Date('2017-01-31T00:00:00+05:30'); console.log("2017-01-01 is printed as ==>", date1); console.log("2017-01-31 is printed as ==>", date2);
内容的提问来源于stack exchange,提问作者Vipin

