Подтвердить что ты не робот

Как перечислить даты между двумя датами в Moment

У меня есть два моментных дата:

var fromDate = moment(new Date('1/1/2014'));
var toDate   = moment(new Date('6/1/2014'));

Предоставляет ли момент способ перечислить все даты между этими двумя датами?

Если нет, есть ли лучшее решение, кроме создания цикла, который увеличивает fromDate на 1, пока не достигнет toDate?

Изменение: Добавление метода и проблемы перечисления даты

Я смоделировал метод для перечисления дней между двумя датами, но столкнулся с проблемой.

  var enumerateDaysBetweenDates = function(startDate, endDate) {
    var dates = [];

    startDate = startDate.add(1, 'days');

    while(startDate.format('M/D/YYYY') !== endDate.format('M/D/YYYY')) {
      console.log(startDate.toDate());
      dates.push(startDate.toDate());
      startDate = startDate.add(1, 'days');
    }

    return dates;
  };

Посмотрите на вывод, когда я запускаю enumerateDaysBetweenDates( moment(new Date('1/1/2014')), moment(new Date('1/5/2014'));

Thu Jan 02 2014 00:00:00 GMT-0800 (PST)
Fri Jan 03 2014 00:00:00 GMT-0800 (PST)
Sat Jan 04 2014 00:00:00 GMT-0800 (PST)
[ Sun Jan 05 2014 00:00:00 GMT-0800 (PST),
  Sun Jan 05 2014 00:00:00 GMT-0800 (PST),
  Sun Jan 05 2014 00:00:00 GMT-0800 (PST) ]

Это console.logging правильные даты, но только окончательная дата добавляется в массив. Как/почему это? Это пахнет чем-то вроде ссылки на переменную - но я этого не вижу.

4b9b3361

Ответ 1

.add() является мутаторным методом, поэтому назначение в этой строке не требуется:

startDate = startDate.add(1, 'days');

Вы можете просто сделать это и иметь тот же эффект:

startDate.add(1, 'days');

Пока это имя подразумевает создание нового объекта Date, метод toDate() действительно просто возвращает существующий внутренний Date объект.

Таким образом, ни один из вызовов вашего метода не создает новые экземпляры объектов Date или moment. Исправьте это, используя .clone(), чтобы получить новый экземпляр:

startDate = startDate.clone().add(1, 'days');

Или еще лучше обернуть значения в вызове moment(), поскольку Mtz предлагает в комментарии, и он будет клонировать экземпляр, если значение - это моментный объект, или он будет анализировать ввод для создания нового моментального экземпляра.

startDate = moment(startDate).add(1, 'days');

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

var enumerateDaysBetweenDates = function(startDate, endDate) {
    var dates = [];

    var currDate = moment(startDate).startOf('day');
    var lastDate = moment(endDate).startOf('day');

    while(currDate.add(1, 'days').diff(lastDate) < 0) {
        console.log(currDate.toDate());
        dates.push(currDate.clone().toDate());
    }

    return dates;
};

Ответ 2

Получил это для вас:

var enumerateDaysBetweenDates = function(startDate, endDate) {
    var now = startDate.clone(), dates = [];

    while (now.isSameOrBefore(endDate)) {
        dates.push(now.format('M/D/YYYY'));
        now.add(1, 'days');
    }
    return dates;
};

Ссылки now а не startDate сделали все различие.

Если вы не ищете инклюзивный поиск, измените .isSameOrBefore на .isBefore

Скрипка: http://jsfiddle.net/KyleMuir/sRE76/118/

Ответ 3

Momentjs не предоставляет этого сам по себе, но есть плагин, который предлагает это: moment-range.

В частности, ознакомьтесь с документацией по итерации.

Ответ 4

Как продолжение ответа Кайла - я пытался заставить это работать с отметками времени Unix, и после многих проб и ошибок я получил его на работу и думал, что отправлю его здесь, если кто-то ищет то же самое вещь и нуждается в ней. Смотрите мой код ниже:

fromDate = moment.unix(req.params.dateFrom).format('YYYY-MM-DD')
toDate = moment.unix(req.params.dateTo).format('YYYY-MM-DD')

// Returns an array of dates between the two dates
function enumerateDaysBetweenDates(startDate, endDate) {
    startDate = moment(startDate);
    endDate = moment(endDate);

    var now = startDate, dates = [];

    while (now.isBefore(endDate) || now.isSame(endDate)) {
        dates.push(now.format('YYYY-MM-DD'));
        now.add(1, 'days');
    }
    return dates;
};

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

Пример использования:

fromDate = '2017/03/11' // AFTER conversion from Unix
toDate = '2017/03/13' // AFTER conversion from Unix

console.log(enumerateDaysBetweenDates(fromDate, toDate));

Вернется:

['2017/03/11', '2017/03/12', '2017/03/13']