moment().add(1, "months") // >> Mon Jul 20 2015 13:36:12 GMT+0200
moment().add(1.9, "months") // >> Mon Jul 20 2015 13:36:12 GMT+0200
// Excpected: Mon Aug 17 2015 09:34:37 GMT+0200
А пока мне нужно сделать:
var duration = moment.duration(1.9, "months");
var ms = duration.asMilliseconds();
var date = moment().add(ms, "ms");
Почему эти методы не могут складывать или вычитать значения с плавающей запятой?
Это задумано, но, вероятно, лучше объяснить в документации.
Вы можете использовать десятичные дроби при сложении или вычитании часов, минут, секунд или миллисекунд, но вы не можете разделить дни или более крупные компоненты.
Причина в том, что существует логическая разница между математикой времени и датой.
Математика времени предполагает линейную шкалу времени, просто увеличивая или уменьшая метку времени на основе UTC. Это обрабатывает переходы на летнее время в реальном времени. Например, для большинства мест в США 2015-03-08T01:00:00
плюс один час будет 2015-03-08T03:00:00
потому что час с 2:00 до 3:00 был пропущен для перехода на летнее время.
Математика дат не использует линейную шкалу времени, а использует даты в календаре. Используя тот же пример, 2015-03-08T01:00:00
плюс один _day_ будет 2015-03-09T01:00:00
, даже если прошло всего 23 часа. Следовательно, «день» в этом контексте не является фиксированным количеством времени, и поэтому его разделение было бы бессмысленным. (Будет ли полдня на 12 часов позже или на 11,5 часов позже в этот день?)
Учтите, что даже без летнего времени не все месяцы равны 30 дням и не все годы равны 365 дням. «Добавление» года на самом деле не означает «добавить 365 дней», это означает «переместить позицию в календаре к тому же месяцу и дню следующего года». Это создает определенную двусмысленность, например, при добавлении одного года к 29 февраля в високосном году и окончании невисокосного года. Мы выбираем приземление 28 февраля, но приземление 1 марта также будет действительным.
В качестве другого примера представьте, что 31 августа плюс один месяц минус один месяц - это 30 августа.
Поскольку математика дат не следует обычным математическим правилам сложения и вычитания, она также не может обрабатывать операции деления или умножения, и поэтому вы не можете добавить 1,9 месяца.
Если подумать по-другому, каков результат полуночи 15 июня + 1,5 месяца? Человек может сделать любое из следующего:
2015-06-15T00:00
+ (0,5 * 30 дней в июне) = 2015-06-30T00:00
+ (1 месяц = 30 дней) = 2015-07-30T00:00
2015-06-15T00:00
+ (0,5 * 30 дней в июне) = 2015-06-30T00:00
+ (1 месяц = 31 день) = 2015-07-31T00:00
2015-06-15T00:00
+ 1 месяц = 2015-07-15T00:00
+ (0,5 * 31 день в июле) = 2015-07-30T12:00
2015-06-15T00:00
+ [(61 день в июне и июле / 2 = 30,5 в среднем дней в эти месяцы) * 1,5 месяца = 45,75 дней] = 2015-07-30T18:00
Итак, вот четыре разных ответа, которые все являются логическими результатами - вот почему вы не можете подразделить единицы при вычислении даты.
Большое спасибо за то, что нашли время написать этот очень подробный ответ. Я лучше понимаю логику работы этих функций.
Я не мог устоять перед собой за то, что поблагодарил Мэтта, я пересек ту же проблему, что и Делган, и дружище! Ваш ответ настолько исчерпывающий, спасибо.
Самый полезный комментарий
Это задумано, но, вероятно, лучше объяснить в документации.
Вы можете использовать десятичные дроби при сложении или вычитании часов, минут, секунд или миллисекунд, но вы не можете разделить дни или более крупные компоненты.
Причина в том, что существует логическая разница между математикой времени и датой.
Математика времени предполагает линейную шкалу времени, просто увеличивая или уменьшая метку времени на основе UTC. Это обрабатывает переходы на летнее время в реальном времени. Например, для большинства мест в США
2015-03-08T01:00:00
плюс один час будет2015-03-08T03:00:00
потому что час с 2:00 до 3:00 был пропущен для перехода на летнее время.Математика дат не использует линейную шкалу времени, а использует даты в календаре. Используя тот же пример,
2015-03-08T01:00:00
плюс один _day_ будет2015-03-09T01:00:00
, даже если прошло всего 23 часа. Следовательно, «день» в этом контексте не является фиксированным количеством времени, и поэтому его разделение было бы бессмысленным. (Будет ли полдня на 12 часов позже или на 11,5 часов позже в этот день?)Учтите, что даже без летнего времени не все месяцы равны 30 дням и не все годы равны 365 дням. «Добавление» года на самом деле не означает «добавить 365 дней», это означает «переместить позицию в календаре к тому же месяцу и дню следующего года». Это создает определенную двусмысленность, например, при добавлении одного года к 29 февраля в високосном году и окончании невисокосного года. Мы выбираем приземление 28 февраля, но приземление 1 марта также будет действительным.
В качестве другого примера представьте, что 31 августа плюс один месяц минус один месяц - это 30 августа.
Поскольку математика дат не следует обычным математическим правилам сложения и вычитания, она также не может обрабатывать операции деления или умножения, и поэтому вы не можете добавить 1,9 месяца.
Если подумать по-другому, каков результат полуночи 15 июня + 1,5 месяца? Человек может сделать любое из следующего:
2015-06-15T00:00
+ (0,5 * 30 дней в июне) =2015-06-30T00:00
+ (1 месяц = 30 дней) =2015-07-30T00:00
2015-06-15T00:00
+ (0,5 * 30 дней в июне) =2015-06-30T00:00
+ (1 месяц = 31 день) =2015-07-31T00:00
2015-06-15T00:00
+ 1 месяц =2015-07-15T00:00
+ (0,5 * 31 день в июле) =2015-07-30T12:00
2015-06-15T00:00
+ [(61 день в июне и июле / 2 = 30,5 в среднем дней в эти месяцы) * 1,5 месяца = 45,75 дней] =2015-07-30T18:00
Итак, вот четыре разных ответа, которые все являются логическими результатами - вот почему вы не можете подразделить единицы при вычислении даты.