初始化JS日期对象从HTML日期选择器:返回的不正确日期



如何正确地将无独立的日期(或者我猜是固定在HTML侧和JS侧的单个时区)的日期),从HTML DatePicker?p>我有以下简单代码,该代码产生了不正确的日期:

function printDate(){
	let d = new Date(document.getElementById("date").value)
	alert(d)
}
document.getElementById("printDate").addEventListener("click", e => printDate())
<html>
<body>
Print Date: <br><input type="date" id="date"> <button id="printDate">Add</button>
</body>
</html>

,但至少在我的电脑上,目前坐在美国山区时代,它会产生不正确的日期。我给它今天的日期(2019年3月9日),它以以下格式提醒昨天的日期:Fri Mar 08 2019 17:00:00 GMT-0700 (MST)。我该如何不这样做?

我真的只希望它假设所有输入和所有输出都在GMT中。

<input type="date" />元素中,所选日期以语言环境格式显示,但是value属性始终以yyyy-mm-dd格式返回,如MDN DOCS中所述。

换句话说,当您选择2019年3月9日时,您可能会在世界其他地区看到03/09/201909/03/2019,但是value是CC_7,无论其任何时区域或本地化设置如何。这是一件好事,因为它允许您以标准ISO 8601格式使用所选日期,而无需尝试应用时间。

但是,当您使用Date对象的构造函数(或使用Date.parse)解析该格式的日期字符串时,您会违反已知问题:该日期不被视为本地时间,而将其视为UTC。这是ISO 8601的对面

MDN文档中描述了这一点:

注意:使用日期构造函数(和Date.parse,它们是等效)的日期字符串解析,由于浏览器差异和不一致而被强烈劝阻。对RFC 2822格式字符串的支持仅是按照约定的。对ISO 8601格式的支持在仅日期的字符串(例如" 1970-01-01")中有所不同。

它也在ecmascript规范(重点是我的)中:

...当缺乏时区偏移时,仅日期表单被解释为UTC时间,而日期时间表格则将其解释为本地时间。

在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将时间设置为中午而不是午夜。这是可选的,但是它避免了在午夜午夜过渡(巴西,古巴等)的本地时区中不存在午夜的情况。

然后是您的最后评论:

我真的只希望它假设所有输入和所有输出都在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'}));
}

最新更新