如何将日期输入和时间输入视为当地时间,而不是世界时间?

Cha*_*kal 5 javascript time timezone date

用户输入的日期输入2019-12-22给出以下值:

  • input.value:"2019-12-22"
  • input.valueAsNumber:1576972800000
  • input.valueAsDate:"Sat Dec 21 2019 16:00:00 GMT-0800 (Pacific Standard Time)"
    • 这个结果日期对象似乎是错误的
    • 当浏览器返回一个值时,它将用户输入视为世界时间
    • 因此日期对象的 utc 表示形式与输入显示给用户的内容相同
    • input.valueAsDate.getUTCDate()返回22,这是用户输入的内容
    • input.valueAsDate.getDate()返回21,而不是用户输入的内容
    • 因此我们得出结论,日期输入显示并接受 UTC 时间,而不是本地时间

我们希望结果date.toString()显示与日期输入中原始用户输入相同的结果

我们如何允许用户与当地时间交互,然后在脚本中获取正确的日期对象?

Rob*_*obG 4

此问题是由 TC-39 决定将 date\xe2\x80\x93only ISO 8601 格式时间戳视为 UTC 引起的,而与 ISO 8601 保持一致并将其视为本地时间戳更为合乎逻辑。请参阅为什么 Date.parse 给出不正确的结果?

\n\n

简单的解决方案是手动解析字符串,不要使用内置的 \xe2\x80\x93in 解析器,作为至少一种当前实现,直到最近将 YYYY-MM-DD 解析为本地。另外,请勿使用当前时区偏移量来调整时间值,因为这不允许偏移量的历史变化或可能的夏令时变化。

\n\n

\r\n
\r\n
// Parse timestamp in YYYY-MM-DD format as local\r\nfunction parseISOLocal(s) {\r\n  let [y, m, d] = s.split(/\\D/);\r\n  return new Date(y, --m, d);\r\n}\r\n\r\n// Format date as YYYY-MM-DD local\r\nfunction formatISOLocal(d) {\r\n  let z = n => (n<10?\'0\':\'\') + n;\r\n  return d.getFullYear() + \'-\' + z(d.getMonth()+1) + \'-\' + z(d.getDate());\r\n}\r\n\r\nlet s = \'2019-12-22\';\r\nlet d = parseISOLocal(s);\r\nconsole.log( d.toString());\r\nconsole.log( formatISOLocal(d));
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

编辑

\n\n

在支持输入类型日期且 YYYY-MM-DD 根据 ECMA-262 解析为 UTC 的情况下,您可以使用valueAsDate和 UTC 方法。但是,并非所有浏览器都支持输入类型日期,并且并非所有解析器都会将该格式解析为 UTC。

\n\n

不依赖输入类型日期并手动解析值、检查格式和有效性要可靠得多。这就是为什么通常使用日期小部件和库而不是日期功能中内置的\xe2\x80\x93 的原因之一。

\n\n

\r\n
\r\n
let inp = document.getElementById(\'dob\');\r\nlet dobObj = inp.valueAsDate;\r\nlet dobStr = inp.value;\r\n\r\nconsole.log(\'Value as date: \' + dobObj);   // Safari: null\r\nconsole.log(\'Value as string: \' + dobStr); // 2018-06-15
Run Code Online (Sandbox Code Playgroud)\r\n
<input id="dob" type="date" value="2018-06-15">
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n