Как перечислить даты между двумя датами в 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 правильные даты, но только окончательная дата добавляется в массив. Как/почему это? Это пахнет чем-то вроде ссылки на переменную - но я этого не вижу.
Ответы
Ответ 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']
Ответ 5
Вы можете легко перечислить с помощью moment.js
Вот более общее решение для дней, недель, месяцев или лет:
https://gist.github.com/gvko/76f0d7b4b61b18fabfe9c0cc24fc3d2a