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

时间:2019-03-10 00:20:56

标签: javascript html date timezone locale

您如何正确地从html datepicker初始化与时区无关的日期(或者我猜为在html端和JS端固定为单个时区的日期)?

我有以下简单的代码,生成的日期不正确:

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中。

1 个答案:

答案 0 :(得分:1)

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

换句话说,当您选择2019年3月9日时,您可能会看到来自美国的03/09/2019或世界其他地方的09/03/2019,但是value是{{1} },无论任何时区或本地化设置。这是一件好事,因为它使您可以使用标准ISO 8601格式处理选定的日期,而无需尝试花费时间。

但是,当您使用2019-03-09对象的构造函数(或Date)解析这种格式的日期字符串时,就会遇到一个已知问题:日期不被视为本地时间,但作为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.parse对象(如果不需要)。换句话说:

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

然后是您的最后一条评论:

  

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

与您显示的内容有些不同。如果确实是您想要的,那么可以像以前一样构造,12对象,并使用Date.toISOString().toGMTString()

.toLocaleString(undefined, {timeZone: 'UTC'})