Почему передача null в аргументе `date` при инициализации даты приводит к предыдущему дню?

#javascript #date

#javascript #Дата

Вопрос:

Какова логика такого поведения? Почему передача null приводит к предыдущему дню?

 JSON.stringify(new Date(Date.UTC(2018, 0, null)));      // "2017-12-31T00:00:00.000Z"
JSON.stringify(new Date(Date.UTC(2018, 0)));            // "2018-01-01T00:00:00.000Z"
JSON.stringify(new Date(Date.UTC(2018, 0, undefined))); // null
 

Ответ №1:

Прочитайте спецификацию. Когда конструктору передается более 1 аргумента, ToNumber вызывается для каждого значения и ToNumber(null) преобразуется в 0 . So:

 Date.UTC(2018, 0, null)
 

это то же самое, что:

 Date.UTC(2018, 0, 0)
 

Поскольку 0 января нет, оно переходит к предыдущему дню, 31 декабря предыдущего года. Это поведение используется в обычной технике для получения последнего дня месяца, а также для вычисления количества дней в месяце.

Комментарии:

1. Спасибо за объяснение! Это действительно проливает свет на это странное явление, но это так неинтуитивно.

Ответ №2:

Я предполагаю, что null преобразуется в число (0).

Параметр day функции должен принимать целое число от 1 до 31. Но после тестирования вы также можете передать нулевые и отрицательные числа, и это «вычтет» дни из даты. Например, передача 0 вычитает 1 день, -1 вычитает 2 дня и т.д.

С другой стороны, undefined нельзя преобразовать в число:

 Number(null) // => 0
Number(undefined) // => NaN
 

Комментарии:

1. Re: » Параметр day функции должен принимать целое число от 1 до 31 » такого ограничения нет, подойдет любое число.