I've been trying to display a datetime in a input box and based on the code snippet below one would think that the text input and datetime-local input would display the same time. But alas, they do not.
Can anyone tell me why, and how I can get it to behave as it "should"?
Image of how it behaves on several of computers I have tested.
const datetime = document.getElementById('datetime');
const expected = document.getElementById('expected');
const date = new Date();
date.setMilliseconds(0)
datetime.valueAsNumber = date;
expected.value = date.toLocaleString();
<h1> Datetime-local bug: </h1>
<input type="datetime-local" id="datetime" />
<input type="text" id="expected" />
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
There are a number of inconsistencies with how browsers render and parse the value of input type="datetime-local"
. In general, it's best to use separate controls for date and time and combine them behind the scenes as needed (perhaps along with time zone information for accurate DST tracking).
For this question, however, the valueAsNumber
property is read-only according the the specification. Some browsers have implemented this differently, as they have the valueAsDate
property, which should be writeable.
Run the following snippet in Edge Version 95.0.1020.53 (Official build) (64-bit) on Windows 10 and it will likely throw an error regarding the input not supporting Date values.
const datetime = document.getElementById('datetime');
const expected = document.getElementById('expected');
const date = new Date();
date.setMilliseconds(0)
datetime.valueAsDate = date;
expected.value = date.toLocaleString();
<h1> Datetime-local bug: </h1>
<input type="datetime-local" id="datetime" />
<input type="text" id="expected" />
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Thus, I suggest setting the value
property to an abbreviated ISO 8601 format (without fractions of seconds, and without time zone).
const datetime = document.getElementById('datetime');
const expected = document.getElementById('expected');
const date = new Date();
date.setMilliseconds(0)
datetime.value = date.toISOString().slice(0, 19);
console.log(datetime.value);
expected.value = date.toLocaleString();
<h1> Datetime-local bug: </h1>
<input type="datetime-local" id="datetime" />
<input type="text" id="expected" />
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Note that the formats will not necessarily be the same. This is due to input type="datetime-local"
using the custom regional settings of the OS, while Date.prototype.toLocaleString
not using those settings. For instance, I prefer to using yyyy-MM-dd HH:mm:ss format (e.g., 2021-11-16 17:46:33) for dates and times, but my language (what some are determined to call "locale") is set as "en-US", which means toLocaleString
wants to format in MM/dd/yyyy h:mm:ss aa format (e.g., 11/16/2021 12:46:33 PM).