Javascript - получить массив дат между 2 датами
var range = getDates(new Date(), new Date().addDays(7));
Я бы хотел, чтобы "диапазон" был массивом объектов даты, по одному на каждый день между двумя датами.
Хитрость заключается в том, что он должен обрабатывать границы месяца и года.
Благодарю.
34 ответа
function (startDate, endDate, addFn, interval) {
addFn = addFn || Date.prototype.addDays;
interval = interval || 1;
var retVal = [];
var current = new Date(startDate);
while (current <= endDate) {
retVal.push(new Date(current));
current = addFn.call(current, interval);
}
return retVal;
}
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
function getDates(startDate, stopDate) {
var dateArray = new Array();
var currentDate = startDate;
while (currentDate <= stopDate) {
dateArray.push(new Date (currentDate));
currentDate = currentDate.addDays(1);
}
return dateArray;
}
Вот функциональная демоверсия http://jsfiddle.net/jfhartsock/cM3ZU/
Я посмотрел все выше. Закончил писать сам. Вам не нужны моменты для этого. Достаточно встроенного цикла for, и оно имеет смысл, поскольку цикл for предназначен для подсчета значений в диапазоне.
Один лайнер:
var getDaysArray = function(s,e) {for(var a=[],d=s;d<=e;d.setDate(d.getDate()+1)){ a.push(new Date(d));}return a;};
Длинная версия
var getDaysArray = function(start, end) {
for(var arr=[],dt=start; dt<=end; dt.setDate(dt.getDate()+1)){
arr.push(new Date(dt));
}
return arr;
};
Список дат между:
var daylist = getDaysArray(new Date("2018-05-01"),new Date("2018-07-01"));
daylist.map((v)=>v.toISOString().slice(0,10)).join("")
/*
Output:
"2018-05-01
2018-05-02
2018-05-03
...
2018-06-30
2018-07-01"
*/
Дни от прошедшей даты до настоящего времени:
var daylist = getDaysArray(new Date("2018-05-01"),new Date());
daylist.map((v)=>v.toISOString().slice(0,10)).join("")
Попробуйте это, не забудьте включить момент JS,
function getDates(startDate, stopDate) {
var dateArray = [];
var currentDate = moment(startDate);
var stopDate = moment(stopDate);
while (currentDate <= stopDate) {
dateArray.push( moment(currentDate).format('YYYY-MM-DD') )
currentDate = moment(currentDate).add(1, 'days');
}
return dateArray;
}
У меня возникли проблемы с использованием приведенных выше ответов. В диапазонах дат отсутствовали отдельные дни из-за сдвига часового пояса, вызванного местным летним временем (DST). Я реализовал версию с использованием дат UTC, которая устраняет эту проблему:
function dateRange(startDate, endDate, steps = 1) {
const dateArray = [];
let currentDate = new Date(startDate);
while (currentDate <= new Date(endDate)) {
dateArray.push(new Date(currentDate));
// Use UTC date to prevent problems with time zones and DST
currentDate.setUTCDate(currentDate.getUTCDate() + steps);
}
return dateArray;
}
const dates = dateRange('2020-09-27', '2020-10-28');
console.log(dates);
Примечание. Применение определенного часового пояса или летнего времени полностью зависит от вашего региона. Заменять это, как правило, не очень хорошая идея. Использование дат в формате UTC устраняет большинство проблем, связанных со временем.
Бонус: вы можете установить временной интервал, для которого вы хотите создать временные метки, с помощью необязательного
steps
параметр. Если вы хотите установить недельные временные метки
steps
к
7
.
Я использую moment.js и Twix.js, они очень хорошо поддерживают манипуляции с датой и временем
var itr = moment.twix(new Date('2012-01-15'),new Date('2012-01-20')).iterate("days");
var range=[];
while(itr.hasNext()){
range.push(itr.next().toDate())
}
console.log(range);
У меня это работает на http://jsfiddle.net/Lkzg1bxb/
var boxingDay = new Date("12/26/2010");
var nextWeek = boxingDay*1 + 7*24*3600*1000;
function getDates( d1, d2 ){
var oneDay = 24*3600*1000;
for (var d=[],ms=d1*1,last=d2*1;ms<last;ms+=oneDay){
d.push( new Date(ms) );
}
return d;
}
getDates( boxingDay, nextWeek ).join("\n");
// Sun Dec 26 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Mon Dec 27 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Tue Dec 28 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Wed Dec 29 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Thu Dec 30 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Fri Dec 31 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Sat Jan 01 2011 00:00:00 GMT-0700 (Mountain Standard Time)
Если вы используете момент, то вы можете использовать их "официальный плагин" для диапазонов moment-range
и тогда это становится тривиальным.
Пример узла диапазона моментов:
const Moment = require('moment');
const MomentRange = require('moment-range');
const moment = MomentRange.extendMoment(Moment);
const start = new Date("11/30/2018"), end = new Date("09/30/2019")
const range = moment.range(moment(start), moment(end));
console.log(Array.from(range.by('day')))
Пример браузера с диапазоном моментов:
window['moment-range'].extendMoment(moment);
const start = new Date("11/30/2018"), end = new Date("09/30/2019")
const range = moment.range(moment(start), moment(end));
console.log(Array.from(range.by('day')))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/4.0.1/moment-range.js"></script>
пример даты fns:
Если вы используете date-fns
затем eachDay
Ваш друг, и вы получите самый короткий и краткий ответ:
console.log(dateFns.eachDay(
new Date(2018, 11, 30),
new Date(2019, 30, 09)
))
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.29.0/date_fns.min.js"></script>
Используя ES6, вы получаете Array.from, что означает, что вы можете написать действительно элегантную функцию, которая учитывает динамические интервалы (часы, дни, месяцы).
function getDates(startDate, endDate, interval) {
const duration = endDate - startDate;
const steps = duration / interval;
return Array.from({length: steps+1}, (v,i) => new Date(startDate.valueOf() + (interval * i)));
}
const startDate = new Date(2017,12,30);
const endDate = new Date(2018,1,3);
const dayInterval = 1000 * 60 * 60 * 24; // 1 day
const halfDayInterval = 1000 * 60 * 60 * 12; // 1/2 day
console.log("Days", getDates(startDate, endDate, dayInterval));
console.log("Half Days", getDates(startDate, endDate, halfDayInterval));
Просто наткнулся на этот вопрос, самый простой способ сделать это - использовать момент:
Сначала нужно установить момент и диапазон моментов:
const Moment = require('moment');
const MomentRange = require('moment-range');
const moment = MomentRange.extendMoment(Moment);
const start = moment()
const end = moment().add(2, 'months')
const range = moment.range(start, end)
const arrayOfDates = Array.from(range.by('days'))
console.log(arrayOfDates)
Я недавно работал с moment.js, после чего добился цели..
function getDateRange(startDate, endDate, dateFormat) {
var dates = [],
end = moment(endDate),
diff = endDate.diff(startDate, 'days');
if(!startDate.isValid() || !endDate.isValid() || diff <= 0) {
return;
}
for(var i = 0; i < diff; i++) {
dates.push(end.subtract(1,'d').format(dateFormat));
}
return dates;
};
console.log(getDateRange(startDate, endDate, dateFormat));
Результат будет:
["09/03/2015", "10/03/2015", "11/03/2015", "12/03/2015", "13/03/2015", "14/03/2015", "15/03/2015", "16/03/2015", "17/03/2015", "18/03/2015"]
Некоторое время я использовал решение @Mohammed Safeer и сделал несколько улучшений. Использование форматированных дат - плохая практика при работе в ваших контроллерах. moment().format()
следует использовать только для отображения в представлениях. Также помните, что moment().clone()
обеспечивает отделение от входных параметров, что означает, что входные даты не изменяются. Я настоятельно рекомендую вам использовать moment.js при работе с датами.
Использование:
- Укажите даты moment.js в качестве значений для
startDate
,endDate
параметры interval
параметр является необязательным и по умолчанию имеет значение "дни". Используйте интервалы, поддерживаемые.add()
метод (moment.js). Подробнее здесьtotal
Параметр полезен при указании интервалов в минутах. По умолчанию 1.
Призовите:
var startDate = moment(),
endDate = moment().add(1, 'days');
getDatesRangeArray(startDate, endDate, 'minutes', 30);
Функция:
var getDatesRangeArray = function (startDate, endDate, interval, total) {
var config = {
interval: interval || 'days',
total: total || 1
},
dateArray = [],
currentDate = startDate.clone();
while (currentDate < endDate) {
dateArray.push(currentDate);
currentDate = currentDate.clone().add(config.total, config.interval);
}
return dateArray;
};
Я использую простой цикл while для расчета между датами
var start = new Date("01/05/2017");
var end = new Date("06/30/2017");
var newend = end.setDate(end.getDate()+1);
var end = new Date(newend);
while(start < end){
console.log(new Date(start).getTime() / 1000); // unix timestamp format
console.log(start); // ISO Date format
var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
}
var listDate = [];
var startDate ='2017-02-01';
var endDate = '2017-02-10';
var dateMove = new Date(startDate);
var strDate = startDate;
while (strDate < endDate){
var strDate = dateMove.toISOString().slice(0,10);
listDate.push(strDate);
dateMove.setDate(dateMove.getDate()+1);
};
console.log(listDate);
//["2017-02-01", "2017-02-02", "2017-02-03", "2017-02-04", "2017-02-05", "2017-02-06", "2017-02-07", "2017-02-08", "2017-02-09", "2017-02-10"]
Array(7).fill().map((_,i) => dayjs().subtract(i, "day").format("YYYY-MM-DD"));
Это еще одно решение на несколько строк с использованием библиотеки date-fns:
Использование JavaScript
const getDatesBetween = (startDate, endDate, includeEndDate) => {
const dates = [];
const currentDate = startDate;
while (currentDate < endDate) {
dates.push(new Date(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}
if (includeEndDate) dates.push(endDate);
return dates;
};
Использование TypeScript
const getDatesBetween = (
startDate: Date,
endDate: Date,
includeEndDate?: boolean
) => {
const dates = [];
const currentDate = startDate;
while (currentDate < endDate) {
dates.push(new Date(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}
if (includeEndDate) dates.push(endDate);
return dates;
};
Пример
console.log(getDatesBetween(new Date(2020, 0, 1), new Date(2020, 0, 3)));
console.log(getDatesBetween(new Date(2020, 0, 1), new Date(2020, 0, 3), true));
Вы можете легко сделать это с помощью momentJS
Добавьте момент к своим зависимостям
npm i moment
Затем импортируйте это в свой файл
var moment = require("moment");
Затем используйте следующий код, чтобы получить список всех дат между двумя датами.
let dates = [];
let currDate = moment.utc(new Date("06/30/2019")).startOf("day");
let lastDate = moment.utc(new Date("07/30/2019")).startOf("day");
do {
dates.push(currDate.clone().toDate());
} while (currDate.add(1, "days").diff(lastDate) < 0);
dates.push(currDate.clone().toDate());
console.log(dates);
Я использую эту функцию
function getDatesRange(startDate, stopDate) {
const ONE_DAY = 24*3600*1000;
var days= [];
var currentDate = new Date(startDate);
while (currentDate <= stopDate) {
days.push(new Date (currentDate));
currentDate = currentDate - 1 + 1 + ONE_DAY;
}
return days;
}
Вот один вкладыш, который не требует каких-либо библиотек на тот случай, если вы не хотите создавать другую функцию. Просто замените startDate (в двух местах) и endDate (которые являются объектами js date) вашими переменными или значениями даты. Конечно, вы можете обернуть его в функцию, если вы предпочитаете
Array(Math.floor((endDate - startDate) / 86400000) + 1).fill().map((_, idx) => (new Date(startDate.getTime() + idx * 86400000)))
Не самый короткий, но простой, неизменный и без зависимостей
function datesArray(start, end) {
let result = [], current = new Date(start);
while (current <= end)
result.push(current) && (current = new Date(current)) && current.setDate(current.getDate() + 1);
return result;
}
Применение
Решение @softvar, но затем с опцией рабочих дат
/**
* Returns array of working days between two dates.
*
* @param {string} startDate
* The start date in yyyy-mm-dd format.
* @param {string} endDate
* The end date in yyyy-mm-dd format.
* @param {boolean} onlyWorkingDays
* If true only working days are returned. Default: false
*
* @return {array}
* Array of dates in yyyy-mm-dd string format.
*/
function getDates(startDate, stopDate, onlyWorkingDays) {
let doWd = typeof onlyWorkingDays ==='undefined' ? false : onlyWorkingDays;
let dateArray = [];
let dayNr;
let runDateObj = moment(startDate);
let stopDateObj = moment(stopDate);
while (runDateObj <= stopDateObj) {
dayNr = runDateObj.day();
if (!doWd || (dayNr>0 && dayNr<6)) {
dateArray.push(moment(runDateObj).format('YYYY-MM-DD'));
}
runDateObj = moment(runDateObj).add(1, 'days');
}
return dateArray;
}
d3js предоставляет множество удобных функций и включает d3.time для удобной манипуляции с датами
Для вашего конкретного запроса:
Универсальное глобальное время
var range = d3.utcDay.range(new Date(), d3.utcDay.offset(new Date(), 7));
или местное время
var range = d3.timeDay.range(new Date(), d3.timeDay.offset(new Date(), 7));
диапазон будет массивом объектов даты, которые попадают в первое возможное значение для каждого дня
Вы можете изменить timeDay на timeHour, timeMonth и т. д. для получения одинаковых результатов на разных интервалах
Вот как я люблю это делать
// hours * minutes * seconds * milliseconds
const DAY_IN_MS = 24 * 60 * 60 * 1000
/**
* Get range of dates
* @param {Date} startDate
* @param {Number} numOfDays
* @returns {array}
*/
const dateRange = (startDate, numOfDays) => {
const startDateMs = startDate.getTime()
// get array of days and map it to Date object
return [...Array(numOfDays).keys()].map(i => new Date(startDateMs + i * DAY_IN_MS))
}
Использование lodash и момента:
const startDate = moment();
_.range(0, 7).map((d) => startDate.clone().add(d, 'day').toDate())
Сгенерируйте массив лет:
const DAYS = () => { const days = [] const dateStart = moment() const dateEnd = moment().add(30, ‘days') while (dateEnd.diff(dateStart, ‘days') >= 0) { days.push(dateStart.format(‘D')) dateStart.add(1, ‘days') } return days } console.log(DAYS())
Сгенерируйте массивы на месяц:
const MONTHS = () => { const months = [] const dateStart = moment() const dateEnd = moment().add(12, ‘month') while (dateEnd.diff(dateStart, ‘months') >= 0) { months.push(dateStart.format(‘M')) dateStart.add(1, ‘month') } return months } console.log(MONTHS())
Сгенерируйте массивы за дни:
const DAYS = () => { const days = [] const dateStart = moment() const dateEnd = moment().add(30, ‘days') while (dateEnd.diff(dateStart, ‘days') >= 0) { days.push(dateStart.format(‘D')) dateStart.add(1, ‘days') } return days } console.log(DAYS())
Примечание: я знаю, что это немного отличается от запрошенного решения, но я думаю, что многие найдут его полезным.
Если вы хотите найти каждый интервал "x" (дни, месяцы, годы и т. Д.) Между двумя датами, то есть moment.js и пакеты расширений момента-момента, включите эту функцию.
Например, чтобы найти каждый 30-й день между двумя датами:
window['moment-range'].extendMoment(moment);
var dateString = "2018-05-12 17:32:34.874-08";
var start = new Date(dateString);
var end = new Date();
var range1 = moment.range(start, end);
var arrayOfIntervalDates = Array.from(range1.by('day', { step: 30 }));
arrayOfIntervalDates.map(function(intervalDate){
console.log(intervalDate.format('YY-M-DD'))
});
getDates = (from, to) => {
const cFrom = new Date(from);
const cTo = new Date(to);
let daysArr = [new Date(cFrom)];
let tempDate = cFrom;
while (tempDate < cTo) {
tempDate.setUTCDate(tempDate.getUTCDate() + 1);
daysArr.push(new Date(tempDate));
}
return daysArr;
}
Для этого я использовал пакет DayJS
Простое объяснение: в dayjs есть функция isBefore, с помощью которой вы можете проверить, предшествует ли дата начала дате окончания. если это станет правдой, поместите эту дату в массив и добавьте 1 день. затем сделайте это в цикле while, и вы получите список дат.
Функция:
var dates = [],
currentDate = startDate,
addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
};
while (currentDate <= endDate) {
dates.push(currentDate);
currentDate = addDays.call(currentDate, 1);
}
return dates;
};
Использование:
var dates = getDatesRange(new Date(2019,01,01), new Date(2019,01,25));
dates.forEach(function(date) {
console.log(date);
});
Надеюсь, это поможет вам