Moment: Это способ .add () или .subtract () значения с плавающей запятой?

Созданный на 20 июн. 2015  ·  3Комментарии  ·  Источник: moment/moment

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

Итак, вот четыре разных ответа, которые все являются логическими результатами - вот почему вы не можете подразделить единицы при вычислении даты.

Все 3 Комментарий

Это задумано, но, вероятно, лучше объяснить в документации.

Вы можете использовать десятичные дроби при сложении или вычитании часов, минут, секунд или миллисекунд, но вы не можете разделить дни или более крупные компоненты.

Причина в том, что существует логическая разница между математикой времени и датой.

Математика времени предполагает линейную шкалу времени, просто увеличивая или уменьшая метку времени на основе 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

Итак, вот четыре разных ответа, которые все являются логическими результатами - вот почему вы не можете подразделить единицы при вычислении даты.

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

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги