在<input type="date" /> 元素中,所选日期以区域设置格式显示,但value 属性始终以yyyy-mm-dd 格式返回,如the MDN docs 中所述。
换句话说,当您选择 2019 年 3 月 9 日时,您可能会看到来自美国的 03/09/2019 或在世界其他地区的 09/03/2019,但无论任何时区或本地化,value 都是 2019-03-09设置。这是一件好事,因为它允许您使用标准 ISO 8601 格式的选定日期,而无需尝试应用时间。
但是,当您使用 Date 对象的构造函数(或使用 Date.parse)解析该格式的日期字符串时,您会遇到一个已知问题:日期不被视为本地时间,而是被视为 UTC。这与 ISO 8601相反。
这被描述为in the MDN docs:
注意: 由于浏览器的差异和不一致,强烈建议不要使用 Date 构造函数(和 Date.parse,它们是等效的)解析日期字符串。仅按惯例支持 RFC 2822 格式字符串。对 ISO 8601 格式的支持的不同之处在于仅日期字符串(例如“1970-01-01”)被视为 UTC,而不是本地。
这也是in the ECMAScript specification(强调我的):
...当时区偏移不存在时,仅日期形式被解释为 UTC 时间,而日期时间形式被解释为本地时间。
有a debate about this in 2015,但最终决定保持与现有行为的兼容性比符合 ISO 8601 更重要。
回到您的问题,如果您不需要,最好不将其解析为Date 对象。换句话说:
function printDate(){
const d = document.getElementById("date").value;
alert(d);
}
如果你真的需要Date 对象,那么最简单的选择就是自己解析值:
function printDate(){
const parts = document.getElementById("date").value.split('-');
const d = new Date(+parts[0], parts[1]-1, +parts[2], 12);
alert(d);
}
注意末尾的,12 将时间设置为中午而不是午夜。这是可选的,但它可以避免在 DST 在午夜转换的当地时区(巴西、古巴等)中不存在午夜时得到错误日期的情况。
然后是你的最后一条评论:
我真的只是希望它假设所有输入和所有输出都在 GMT 中。
这和你展示的有点不同。如果这确实是您想要的,那么您可以像以前一样构造Date 对象,并使用.toISOString()、.toGMTString() 或.toLocaleString(undefined, {timeZone: 'UTC'})
function printDate(){
const d = new Date(document.getElementById("date").value); // will treat input as UTC
// will output as UTC in ISO 8601 format
alert(d.toISOString());
// will output as UTC in an implementation dependent format
alert(d.toGMTString());
// will output as UTC in a locale specific format
alert(d.toLocaleString(undefined, {timeZone: 'UTC'}));
}