Почему аргумент месяца варьируется от 0 до 11 в конструкторе даты Java?

При инициализации нового объекта Date в JavaScript с использованием приведенного ниже вызова выяснилось, что аргумент месяца рассчитывает начиная с нуля.

new Date(2010, 3, 1);  // that the 1st April 2010!

Почему аргумент месяца начинается с 0? С другой стороны, аргумент дня месяца (последний) - это число от 1 до 31. Есть ли веские причины для этого?

Ответ 1

Это старая (вероятно, неудачная, вероятно, умирающая) традиция в мире программирования, см. функцию localtime C старого стандарта (POSIX) http://linux.die.net/man/3/localtime

Ответ 2

Реальный ответ на этот вопрос заключается в том, что он был скопирован из java.util.Date, который также имел эту причуду. Доказательство можно найти в Twitter от Брендана Эйха - парня, который изначально реализовал JavaScript (включая объект Date):

https://twitter.com/BrendanEich/status/481939099138654209

first tweet

https://twitter.com/BrendanEich/status/771006397886533632

second tweet

Это произошло в 1995 году, а JDK 1.0 - в бета-версии. Он был запущен в 1996 году. В 1997 году вышел JDK 1.1, который отказался от подавляющего большинства функций на java.util.Date, переместив их на java.util.Calendar, но даже в том, что все еще был месяц с нулевым значением. Разработчики, получившие это, создали библиотеку Joda-Time, которая в итоге привела к пакету java.time, который испекли на Java 8 (2014).

Короче говоря, потребовалось 18 лет для Java, чтобы получить правильно разработанный API-интерфейс даты и времени, но JavaScript все еще застрял в темные века. У нас действительно есть отличные библиотеки, такие как Moment.js, date-fns и js-joda. Но на данный момент для языка нет ничего, кроме Date. Надеюсь, это изменится в ближайшем будущем.

Ответ 3

Все, кроме дня месяца, основано на 0, см. здесь полный список, включая диапазоны:)

Это на самом деле 1 основанные дни, которые являются странными здесь... как ни странно. Почему это было сделано? Я не знаю... но, вероятно, случилось ту же встречу, которую они оштукатурили, и решили, что точки с запятой являются необязательными.

Ответ 4

Есть всегда 12 месяцев в году, поэтому ранние реализации C могли использовать статический массив с фиксированной шириной с индексами 0..11.

Ответ 5

Это похоже на java тоже.. Вероятно, чтобы преобразовать int в строку (0 - jan, 1-feb), они закодированы таким образом.. потому что они могут иметь массив строк ( индексируется из 0) имен месяцев и этих номеров месяцев, если они начинаются с 0, будет легче сопоставить строки месяца.

Ответ 6

Это может быть недостаток, но это также очень удобно, когда вы хотите представить месяцы или день недели в виде строки, которую вы можете просто создать массив вроде ['jan,' feb '... и т.д.] [new Date(). GetMonth()] вместо ['', 'jan', feb... и т.д.] [New Date(). GetMonth()] или ['jan', 'feb'... и т.д.] [ new Date(). getMonth() - 1]

дни месяца нормальны не названы, поэтому вы не будете создавать массивы с именами для них. В этом случае 1-31 легче обрабатывать, поэтому вы хотите, чтобы каждый раз вычитал 1...

Ответ 7

Возможно, они считали месяцы перечислением (первый индекс равен 0) и днями, так как у них нет имени, связанного с ними.

Или, скорее, они считали, что число дней было фактическим представлением дня (так же, как месяцы представляются в виде чисел в дате, например 12/31), как если бы вы могли сделать перечисление с числами в качестве переменных, но фактически на основе 0.

Итак, в течение месяцев, возможно, они думали, что правильное представление перечисления будет состоять в том, чтобы использовать имя месяца, а не цифры, и они сделали бы то же самое, если бы у дней было представление имени. Представьте себе, если бы мы сказали, что в январе пятый, январь шестой, вместо 5 января, 6 января и т.д., То, возможно, они также сделали бы подсчет на основе 0 в течение нескольких дней...

Возможно, подсознательно они думали о перечислении в течение нескольких месяцев как {январь, февраль,...} и в течение дней как {Один, Два, Три,...}, за исключением дней, когда вы обращаетесь к дню в виде числа, а не имя, как 1 для одного и т.д., поэтому невозможно начинать с 0...

Ответ 8

Я знаю, что это не ответ на исходный вопрос, но я просто хотел показать вам свое предпочтительное решение этой проблемы, которое я никогда не запоминаю, поскольку оно появляется время от времени.

Маленькая функция zerofill делает трюк, заполняющий нули там, где это необходимо, и месяц добавляется только +1:

function zerofill(i) {
    return (i < 10 ? '0' : '') + i;
}

function getDateString() {
    const date = new Date();
    const year = date.getFullYear();
    const month = zerofill(date.getMonth()+1);
    const day = zerofill(date.getDate());
    return year + '-' + month + '-' + day;
}

Но да, дата имеет довольно неинтуитивный API, я смеялся, когда читал Brendan Eich Twitter.