Запутанный цикл дат в момент js

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

Вот мой код.

var beforeSevenDays = moment(Date.now() - 7 * 24 * 3600 * 1000).format('YYYY-MM-DD');
var i = 0;
for (var m = moment(beforeSevenDays); m.diff(moment(Date.now()).local('in'), 'days') <= 0; m.add(1, 'days')) {
    console.info("i: " + i + " " + m.format('YYYY-MM-DD'));
    i += 1;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>

когда я запускаю этот код, я получаю

i: 0 2018-10-03
i: 1 2018-10-04
i: 2 2018-10-05
i: 3 2018-10-06
i: 4 2018-10-07
i: 5 2018-10-08
i: 6 2018-10-09
i: 7 2018-10-10
i: 8 2018-10-11

но ожидаемый результат

i: 0 2018-10-03
i: 1 2018-10-04
i: 2 2018-10-05
i: 3 2018-10-06
i: 4 2018-10-07
i: 5 2018-10-08
i: 6 2018-10-09
i: 7 2018-10-10

здесь, когда я изменяю запрос как m.diff(moment(Date.now()).local('in'), 'days') < 0, я получаю вывод как

i: 0 2018-10-03
i: 1 2018-10-04
i: 2 2018-10-05
i: 3 2018-10-06
i: 4 2018-10-07
i: 5 2018-10-08
i: 6 2018-10-09

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
983
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема с вашим кодом заключается в том, что вы сравниваете полные даты, moment(Date.now()) создает момент времени, который включает дату и время, поэтому ваш результат зависит от времени, когда вы его выполняете.

Предлагаю использовать startOf('day'), чтобы:

Mutates the original moment by setting it to the start of a unit of time.

Вот живой образец:

var beforeSevenDays = moment().subtract(7, 'days').format('YYYY-MM-DD');
var today = moment().startOf('day');
var i = 0;
for (var m = moment(beforeSevenDays); m.diff(today, 'days') <= 0; m.add(1, 'days')) {
    console.info("i: " + i + " " + m.format('YYYY-MM-DD'));
    i += 1;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>

Боковое примечание: вы можете просто использовать moment(), чтобы получить текущую дату и время, нет необходимости использовать Date.now(), более того, вы можете использовать subtract(), чтобы получить 7 дней назад без выполнения математической операции, наконец, нет необходимости использовать local() (не смешивайте его с locale() ) с момента создаются по умолчанию в локальном режиме.

Отличный совет в боковых заметках!

dubes 10.10.2018 12:13

Путаница, по-видимому, связана с тем, как moment по-разному конструирует days. Если вычесть только часть даты, это будет похоже на другой день, но вы запрашиваете даты у moment для diff. Итак, какой момент - это найти разницу в некоторых единицах времени и преобразовать их в дни.

Как видно из приведенного ниже фрагмента, разница в днях равна 0, а разница в часах - не 0. Итак, вам нужно заморозить время на что-то, например startOf('day')

var beforeSevenDays = moment(Date.now() - 7 * 24 * 3600 * 1000).format('YYYY-MM-DD');
var i = 0;
for (var m = moment(beforeSevenDays); m.diff(moment(Date.now()).local('in'), 'days') <= 0; m.add(1, 'days')) {
  console.info("diff in hours is: " + m.diff(moment(Date.now()).local('in'), 'hours'))
  console.info("diff in days is: " + m.diff(moment(Date.now()).local('in'), 'days'))
  console.info("diff in days with startOf is: " + m.diff(moment(Date.now()).startOf('day').local('in'), 'days'))
  console.info("i: " + i + " " + m.format('YYYY-MM-DD'));
  i += 1;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>

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

var moment =require('moment');

var beforeSevenDays = moment().subtract(7, 'days').format('YYYY-MM-DD');
var i = 0;

for (var m = moment(beforeSevenDays); m.diff(moment(Date.now()), 'days') <0 || m.isSame(moment(), 'day'); m.add(1, 'days')) {
    console.info("i: " + i + " " + m.format('YYYY-MM-DD'));
    i += 1;
}

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

Другие вопросы по теме