Получить дату ISO строку без времени в JavaScript
Есть ли способ получить строку ISO нового типа даты в javascript со временем в полночь, не перестраивая новую дату с частями даты и не форматируя ее?
Я пытался это
var date = new Date();
date.setHours(0, 0, 0, 0);
document.write(date.toISOString());
и я получаю это
2017-04-20T04:00:00.000Z
Я хочу получить это
2017-04-20T00:00:00.000Z
Есть ли встроенная функция или способ, который я пытался сделать, чтобы получить желаемый результат (с перестроением объекта даты с частями даты)?
7 ответов
Просто используйте setUTCHours
вместо setHours
:
var date = new Date();
date.setUTCHours(0, 0, 0, 0);
document.write(date.toISOString())
setHours
установит время в вашем местном часовом поясе, но когда вы его отобразите, оно покажет время в UTC. Если вы просто установите его как UTC с самого начала, вы получите желаемый результат.
var date=new Date();
var corrected = date.toISOString().substring(0,10);
alert(corrected);
Если вы хотите, чтобы ваш код был логически постоянным, поскольку подстрока на основе жестко закодированных индексов никогда не бывает безопасной:
var iso = date.toISOString()
iso = iso.substr(0, iso.indexOf('T'))
Один лайнер, без сторонней библиотеки:
const date = new Date().toISOString().split('T')[0]; // Ex: '2023-01-17'
Если вы можете жить в зависимости от великолепной библиотеки https://momentjs.com/docs/, это будет так просто:
moment().format('YYYY-MM-DD');
или же
moment().toISOString();
Проблема с большинством ответов здесь, включая ответ user11580699 , что он будет сталкиваться с преобразованиями границ дня в определенных комбинациях часового пояса и времени. т.е. вы хотите получить сегодняшнюю дату в полночь, но поскольку в системе установлен часовой пояс с отрицательным смещением, она получит завтрашнюю дату (или наоборот - получит вчерашнюю дату , если ваша система настроена на часовой пояс с положительным смещением).
Ответ user7602518 имеет правильную идею, но на самом деле он неверен для всех часовых поясов + комбинаций времени, и это только случайно для тех комбинаций, где он правильный .
Прежде чем мы перейдем к правильной реализации ответа Педро, давайте рассмотрим наши предположения и докажем наши утверждения:
Прежде всего, важно помнить, что смещения часовых поясов всегда добавляются к времени UTC, чтобы получить местное время. Подумайте об этом на простом примере: в Лондоне 12 часов дня, в Париже — 13 часов. Смещение часового пояса для Парижа равно +1, поэтому в формуле это выражается как:
Local Time = UTC Time + Offset UTC Time = Local Time - Offset
Во-вторых, когда мы вызываем JS, JS получает текущее системное время, текущие настройки часового пояса системы (можно подтвердить, проверив
Intl.DateTimeFormat().resolvedOptions().timeZone
в консоли JS) и использует эту информацию для преобразования времени в формате UTC (поскольку все объекты JS хранятся в формате UTC) и не преобразует результат обратно в местное время. Итак, в нашем примере, если в системе установлено ровно 1 июня в полночь по часовому поясу Парижа, вызовnew Date().toISOString()
вернется2023-05-31T23:00:00.000Z
В-третьих, чего хочет спрашивающий, так это форматирования JS.
Date.toISOString()
, но без преобразования в часовой пояс UTC, т.е.2023-06-01T00:00:00.000
. Поскольку все объекты даты JS изначально хранятся в формате UTC, самый простой способ сделать это — просто разрешить преобразование JS в UTC, а затем отменить его.Чтобы отменить преобразование, мы должны начать с единой базы, т. е. не меняющейся в зависимости от настроек часового пояса и/или локали системы. Надежный выбор здесь
Date.getTime
. Когда мы звонимnew Date().getTime()
, он вернет количество секунд, прошедших с начала эпохи, и эти секунды представляют собой простое целое число — без привязки к часовому поясу. Неявно предполагается, что часовой пояс — UTC, и все методы JS основаны на этом предположении. Поскольку мы хотим отменить преобразование UTC, которое уже произошло , когда JS создал объект Date, нам нужно использовать формулу для местного времени, но принимая ее обратную, то есть нам нужно вычесть обратно добавленное ранее смещение . Таким образом, мы получаем следующие формулы:Local Time = UTC Time - Offset UTC Time = Local Time + Offset
Объединив все вышеперечисленное, мы можем придумать метод очень общего назначения, который преобразует объект даты JS в «строку ISO», но отформатированную в местном часовом поясе:
// jsDateToISOLocalStr
// Converts a JS date to a "ISO-style" string (i.e. not converting to UTC Zero Offset Time)
// i.e. Suppose it is May 2, 2023 @ 4:36 AM, and we are on a system with a +10 timezone (around Australia)
// The difference between 'toISOString' builtin and jsDateToISOLocalStr is simply as thus:
// new Date().toISOString() --> '2023-05-01T18:36:31.866Z'
// jsDateToISOLocalStr() --> '2023-05-02T04:36:31.866'
// All JS Date objects are stored as UTC, and so if a local timezone is displayed by JS, we must "convert back"
// params:
// * d (optional) -- anything that can be parsed by JS new Date constructor
// returns -- One of the below:
// * if d can be parsed by JS Date: an ISO-style string representation of d according to local (machine) time
// * if d is not truthy or not passed in: an ISO-style string representation of 'right now' according to local time
// * if d cannot be parsed by JS date (that is, when new Date(d) returns "Invalid Date"): null
export const jsDateToISOLocalStr = (d) => {
let retVal = null;
// We necessarily do some string parsing because JS Date doesn't parse dates consistently
// e.g. -- new Date("2023-05-01") returns midnight at UTC,
// new Date("2023-05-01 ") (or any non-strict variant) returns midnight in the local timezone
// We will force to the local time unless any time component is already in the string
// If the total string length is less than 11, then there isn't any time component.
const parsedInput = (typeof d === "string" || d instanceof String) && d.length < 11 ? `${d} ` : d;
// We must not pass a date argument if we want today's date. "new Date(null)" returns the epoch (Jan 1 1970)!
const utcDate = d ? new Date(parsedInput) : new Date();
if (String(utcDate).toLowerCase() !== "invalid date") {
// Conversion to UTC already took place -- now we must *undo* that
const localTimestamp = utcDate.getTime() - utcDate.getTimezoneOffset() * 60 * 1000;
const localDate = new Date(localTimestamp);
// Remove the final trailing 'Z' to indicate local time
retVal = localDate.toISOString().slice(0, -1);
}
return retVal;
};
Теперь мы наконец можем получить желаемый результат:
const isoLocalDateTime = jsDateToISOLocalStr();
const isoLocalDate = isoLocalDateTime.split("T")[0];
// To write the local date set to midnight time
document.write(`${isoLocalDate}T00:00:00.000`);
// Optionally, to write the local date set to the current time
document.write(isoLocalDateTime);
// Optionally, to just write the local date with no time component
document.write(isoLocalDate);
import {format} from "date-fns-tz"
format(new Date(), 'yyyy-MM-dd')