Unfortunately, the previous answers did not work properly for me, because they suggest considering UTC time as my local time (which is, generally saying, incorrect).
For example, if my local time is 2021-03-10T01:50:55+0200, then date.toISOString() returns 2021-03-09T23:50:55Z, so I cannot just cut Z at the end, because for datetime-local I need local datetime 2021-03-10T01:50:55, NOT 2021-03-09T23:50:55.
So, the fixed code would be the following:
const d = new Date();
const dateTimeLocalValue = (new Date(d.getTime() - d.getTimezoneOffset() * 60000).toISOString()).slice(0, -1);
$('#myTextbox').val(dateTimeLocalValue);
That's why it works: we still use the trick of removing trailing "Z" from UTC's time format, but before doing it, we shift the time by our time zone offset (returning by date.getTimezoneOffset() in minutes) in the backward direction. After that, the shifted time, converted to UTC, provides the same date & time that our local. Of course, actually, the shifted time is a different moment, but we don't care as soon as its date & time in UTC matches our date & time in the local timezone.
With the example above, it works the following way:
- shift local time by timezone offset in opposite direction (e.g. if it was UTC+2, then we make even further from UTC):
2021-03-10T01:50:55+0200 -> 2021-03-10T03:50:55+0200 (by - date.getTimezoneOffset() * 60000, because 1 minute is 60000 milliseconds)
- return date&time values back by converting to UTC:
2021-03-10T03:50:55+0200 -> 2021-03-10T01:50:55Z (by .toISOString())
- remove trailing
Z to get real local time with the suited format for <input type="datetime-local"> (by .slice(0, -1))
If someone needs back transformation, from input value to js Date, then we just need to do the same steps in the reverse order:
const dateTimeLocalValue = $('#myTextbox').val();
const fakeUtcTime = new Date(`${dateTimeLocalValue}Z`);
const d = new Date(fakeUtcTime.getTime() + fakeUtcTime.getTimezoneOffset() * 60000);
console.log(d);
Any questions are welcome)