Expand date range using JS? - javascript

I have this variable {{ $daterange }} with json like this
{
"starts_at": "2020-05-20",
"ends_at": "2020-05-23"
},
{
"starts_at": "2020-05-24",
"ends_at": "2020-05-26"
},
{
"starts_at": "2020-05-27",
"ends_at": "2020-05-29"
}
What I want to do is to expand something like this,
2020-05-20
2020-05-21
2020-05-22
2020-05-23
2020-05-24
2020-05-25
2020-05-26
2020-05-27
2020-05-28
2020-05-29
I'm planning to assign these dates inside of expandedDate variable
var expandedDate = [ ....dates ];
This should be done using jquery/js
UPDATE*
Recently this code works and can get all dates between 2 dates. It will list down all dates between 2 date range written in the code.
// Returns an array of dates between the two dates
var getDates = function(startDate, endDate) {
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;
};
// Usage
var dates = getDates(new Date(2013,10,22), new Date(2013,11,25));
dates.forEach(function(date) {
console.log(date);
});
How can I populate {{ $daterange }} contains multiple date range.

Think I missed your update with existing code. The following code seems to get the desired output using javascript. Just added comments to each step as an explanation. Hope it is helpful.
//sample input data
var daterange = [{
"starts_at": "2020-05-27",
"ends_at": "2020-06-23"
},
{
"starts_at": "2020-05-24",
"ends_at": "2020-05-26"
},
{
"starts_at": "2020-05-27",
"ends_at": "2020-05-29"
}
];
// function to get dates between two dates
var getDaysAsArray = function(start_date, end_date) {
for (var arr = [], d = new Date(start_date); d <= end_date; d.setDate(d.getDate() + 1)) {
arr.push(new Date(d));
}
return arr;
};
// function to convert date into the format yyyy-mm-dd
var getFormattedDay = function(date) {
day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
month = date.getMonth()+1 < 10 ? "0" + (date.getMonth()+1) : date.getMonth()+1;
year = date.getFullYear();
return year + "-" + month + "-" + day;
}
//main logic
var expandedDate = [];
//Iterate through the list of arrays in the date range
for (var key in daterange) {
//get first pair of from and to date
var from_string = daterange[key].starts_at;
var to_string = daterange[key].ends_at;
// convert the string date to date format for from and to.
var from_date = new Date(from_string.replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3"));
var to_date = new Date(to_string.replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3"));
// call getDaysAsArray to convert dates into strings and into an array.
var daylist = getDaysAsArray(from_date, to_date);
// iterate through the daylist and push it into the final array you want to use
for (var day in daylist) {
expandedDate.push(getFormattedDay(daylist[day]));
}
}
// final result required
console.log(expandedDate);

Here's the complete code on how to solve this question
Based on #thommu
var daterange = [
{
"starts_at": "2020-05-24",
"ends_at": "2020-05-26"
},
{
"starts_at": "2020-05-27",
"ends_at": "2020-05-29"
}
];
// function to get dates between two dates
var getDaysAsArray = function(start_date, end_date) {
for (var arr = [], d = new Date(start_date); d <= end_date; d.setDate(d.getDate() + 1)) {
arr.push(new Date(d));
}
return arr;
};
// function to convert date into the format yyyy-mm-dd
var getFormattedDay = function(date) {
day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
month = date.getMonth() < 10 ? "0" + date.getMonth() : date.getMonth();
year = date.getFullYear();
return year + "-" + month + "-" + day;
}
//main logic
var expandedDate = [];
//Iterate through the list of arrays in the date range
for (var key in daterange) {
//get first pair of from and to date
var from_string = daterange[key].starts_at;
var to_string = daterange[key].ends_at;
// convert the string date to date format for from and to.
var xfrom_date = new Date(from_string.replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3"));
var xto_date = new Date(to_string.replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3"));
//Add +1 month to correct the data
var from_date = new Date(xfrom_date.setMonth(xfrom_date.getMonth()+1));
var to_date = new Date(xto_date.setMonth(xto_date.getMonth()+1));
// call getDaysAsArray to convert dates into strings and into an array.
var daylist = getDaysAsArray(from_date, to_date);
// iterate through the daylist and push it into the final array you want to use
for (var day in daylist) {
expandedDate.push(getFormattedDay(daylist[day]));
}
}
//Filter Duplicated Dates
var dateDuplicate = expandedDate;
var uniqueDate = [];
$.each(dateDuplicate, function(i, el){
if($.inArray(el, uniqueDate) === -1) uniqueDate.push(el);
});
// final result required
console.log(uniqueDate);

Related

create array of array of datepairs that have gap of n days between them

Consider 2 dates, format will be MM/DD/YYYY
1st date = today
2nd date = 45 days from today
Note: Here, the 1st date and 2nd date are variable.
i.e. 1st date that is today can be tomorrow or any other date. 2nd date can be 15 days, 24 days, 105 days i.e. this "n" can also vary.
Assuming the above 2 dates as startDate and stopDate. I want to create array of datePairs of a given gap between them.
For e.g. if startDate = 12/01/2022 & stopDate = 12/20/2022. I want to have datePairs having gap of 2 (n = 2) days between them. So, the output array should look like
[
['12/01/2022', '12/03/2022'],
['12/04/2022', '12/06/2022'],
['12/07/2022', '12/09/2022'],
['12/10/2022', '12/12/2022'],
['12/13/2022', '12/15/2022'],
['12/16/2022', '12/18/2022'],
['12/19/2022', '12/20/2022']
]
NOTE: Here, the last array does not have the gap of 2 dates because it's just 1 day away from the stopDate. In such case, the last pair can have less gap between them.
The only condition is the above array length should always be even.
Date.prototype.addDays = function (days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
};
function splitInto(array, size, inplace) {
var output, i, group;
if (inplace) {
output = array;
for (i = 0; i < array.length; i++) {
group = array.splice(i, size);
output.splice(i, 0, group);
}
} else {
output = [];
for (i = 0; i < array.length; i += size) {
output.push(array.slice(i, size + i));
}
}
return output;
}
function getDates(startDate, stopDate) {
var dateArray = new Array();
var currentDate = startDate;
var i = 0;
while (currentDate <= stopDate) {
if (i % 2 == 1) {
const options = {
year: 'numeric'
};
options.month = options.day = '2-digit';
var formattedCSTDate = new Intl.DateTimeFormat([], options).format(currentDate);
dateArray.push(formattedCSTDate);
currentDate = currentDate.addDays(1);
} else {
const options = {
year: 'numeric'
};
options.month = options.day = '2-digit';
var formattedCSTDate = new Intl.DateTimeFormat([], options).format(currentDate);
dateArray.push(formattedCSTDate);
currentDate = currentDate.addDays(3);
}
i = i + 1;
}
return dateArray;
};
var dateArray = getDates(new Date(), (new Date()).addDays(43));
var datePairLength = 2;
var rangeArray = splitInto(dateArray, datePairLength, false);
console.log(rangeArray);
It seems to me you're making it more complicated than it needs to be. Just build each range as an array and avoid the splitInto function. You might use a date library (there are many to chose from) for adding days and formatting:
function makeRanges(start = new Date(), end = new Date(), interval = 1) {
let f = new Intl.DateTimeFormat('default', {
year:'numeric',month:'short',day:'2-digit'
});
let s = new Date(start);
let ranges = [];
while (s < end) {
let t = new Date(s);
t.setDate(t.getDate() + interval);
ranges.push([f.format(s), t < end? f.format(t) : f.format(end)]);
s.setDate(s.getDate() + interval + 1)
}
return ranges;
}
console.log(
makeRanges(new Date(2022,0,1), new Date(2022,1,1), 2)
);

JavaScript: How to get simple date without timezone

I have code that generates random dates in a date range, which gives me dates which, when logged, produce this format:
Wed Sep 25 2019 05:00:00 GMT+0500 (Pakistan Standard Time)
I just want to get the date without timezone and Day specifically like this:
2019-09-25
I am trying to get random dates between specified dates using the following code:
var startDate = new Date("2019-08-26"); //YYYY-MM-DD
var endDate = new Date("2019-09-25"); //YYYY-MM-DD
var getDateArray = function(start, end) {
var arr = new Array();
var dt = new Date(start);
while (dt <= end) {
arr.push(new Date(dt));
dt.setDate(dt.getDate() + 1);
}
return arr;
}
var dateArr = getDateArray(startDate, endDate);
function shuffle(arra1) {
var ctr = arra1.length, temp, index;
// While there are elements in the array
while (ctr > 0) {
// Pick a random index
index = Math.floor(Math.random() * ctr);
// Decrease ctr by 1
ctr--;
// And swap the last element with it
temp = arra1[ctr];
arra1[ctr] = arra1[index];
arra1[index] = temp;
}
return arra1; }
console.log(shuffle(dateArr));
It's not a duplicate question as I was trying to achieve different and very specific formate.
One solution would be to map each item of arra1 through a custom formating function (ie formatDate()) where .getDate(), .getMonth() and .getYear() are used to populate the formatted string:
function formatDate(date) {
const year = date.getFullYear();
/* getMonth returns dates from 0, so add one */
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}-${month < 10 ? '0' : ''}${ month }-${ day < 10 ? '0' : '' }${day}`
}
Some points to consider here are:
Date#getMonth() returns 0-indexed dates in the range of 0-11. To match the desired date format, you should add 1 as shown
Check for day and month values that are less than 10 and prefix a 0 to pad those numbers to obtain the desired formatting
This can be added to your existing code as shown:
var startDate = new Date("2019-08-26"); //YYYY-MM-DD
var endDate = new Date("2019-09-25"); //YYYY-MM-DD
function formatDate(date) {
const year = date.getFullYear();
/* getMonth returns dates from 0, so add one */
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}-${month < 10 ? '0' : ''}${ month }-${ day < 10 ? '0' : '' }${day}`
}
var getDateArray = function(start, end) {
var arr = new Array();
var dt = new Date(start);
while (dt <= end) {
arr.push(new Date(dt));
dt.setDate(dt.getDate() + 1);
}
return arr;
}
var dateArr = getDateArray(startDate, endDate);
function shuffle(arra1) {
var ctr = arra1.length,
temp, index;
// While there are elements in the array
while (ctr > 0) {
// Pick a random index
index = Math.floor(Math.random() * ctr);
// Decrease ctr by 1
ctr--;
// And swap the last element with it
temp = arra1[ctr];
arra1[ctr] = arra1[index];
arra1[index] = temp;
}
/* Update this line */
return arra1.map(formatDate);
}
console.log(shuffle(dateArr));
Use .toISOString() and .substr(). Example:
var dt = new Date("2019-09-25");
console.log(dt.toISOString().substr(0,10)); // 2019-09-25
The advantage of this approach is that the Date object has the .toISOString() method built-in, so you don't have to reinvent the wheel. That method returns a full ISO string, though, like "2019-09-25T00:00:00.000Z". So, you can use .substr to retrieve only the part you want to use.
var getDates = function(startDate, endDate) {
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;
};
// Usage
var dates = getDates(new Date(2019, 10, 22),
new Date(2019, 11, 25));
dates.forEach(function(date) {
console.log(date);
});

Getting an array of days five days into the future fails

I am using moment js to get the date five days into the future with this code
//current date
var cd = moment().format("DD-MM-YYYY");
//5 days into the future
var nd = moment(cd, "DD-MM-YYYY").add(5, 'days').format('DD-MM-YYYY');
//get all dates from today to 5 days into the future
and now i am attempting to get an array of days between current date and the future date which is five days later
//current date
var cd = moment().format("DD-MM-YYYY");
//5 days into the future
var nd = moment(cd, "DD-MM-YYYY").add(5, 'days').format('DD-MM-YYYY');
//get all dates from today to 5 days into the future
console.log("start",cd);
console.log("end",nd);
var getDates = function(startDate, endDate) {
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;
};
// Usage
var dates = getDates(cd, nd);
dates.forEach(function(date) {
console.log(date);
});
This is the demo https://jsfiddle.net/codebreaker87/z9d5Lusv/67/
The code only generates the current date. How can i generate an array of all dates between?.
If you are using momentjs already, then you seem to be doubling its functinality by your own code.
Consider the following snip:
var getDates = function( cd, nd ){
var dates = [];
var now = cd.clone();
for(var i = 0; i < nd.diff(cd, 'days') ; i++){
// format the date to any needed output format here
dates.push(now.add(i, 'days').format("DD-MM-YYYY"));
}
return dates;
}
var r = getDates( moment(), moment().add(10, 'days'));
// r now contains
["04-11-2016", "05-11-2016", "07-11-2016", "10-11-2016", "14-11-2016", "19-11-2016", "25-11-2016", "02-12-2016", "10-12-2016", "19-12-2016"]
I managed to solve it like this
//current date
var cd = moment().format("YYYY-MM-DD");
//5 days into the future
var nd = moment(cd, "YYYY-MM-DD").add(5, 'days').format('YYYY-MM-DD');
//get all dates from today to 5 days into the future
var getDates = function(startDate, endDate) {
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 = getDates(new Date(cd), new Date(nd));
dates.forEach(function(date) {
//format the date
var ald = moment(date).format("YYYY-MM-DD");
console.log(ald);
console.log(date);
});

Convert date string into proper date in Javascript

I get an array with dates as string from the server, now I want to filter only day, month and year. How can I format the filter result to a certain date format?
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00', ...];
//wanted result: 2015-02-04 or 04.02.2015
You could convert your what's look to be an ISO Date format like this:
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00'];
date.map(function(_d) {
var d = new Date(_d)
return d.getFullYear() + '-' + d.getMonth() + 1 + '-' + d.getDay()
}
// if you want to get fancy, you could throw in this function to pad the days and months:
var pad = function (n) {return n<10? '0'+n:''+n;}
var sorted = date.map(function(_d) {
var d = new Date(_d)
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDay())
})
console.log(sorted);
Date can take an argument of a string. Use a for loop to iterate through your list, and then make a new Date object for each one.
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00']
var dateObjects = [];
for (var i = 0; i<date.length; i++) {
d = new Date(date[i]);
dateObjects.push(d);
}
Or, in a single line:
var dateObjects = date.map( function (datestr) {return new Date(datestr)} );
Now, you can find the month, day, and year from one of these by the following methods:
var year = dateObjects[0].getFullYear(); // Gets the year
var month = dateObjects[0].getMonth()+1; // Gets the month (add 1 because it's zero-based)
var day = dateObjects[0].getDate(); // Gets the day of the month
dateObjects[0] is just an example that refers to the first date in the list.
So you can then get your output string like
var dateStrings = dateObjects.map(function (item) {
return item.getFullYear()+"-"+(item.getMonth()+1)+"-"+item.getDate();
})
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00'];
var newdateobject = [];
$.each( date, function(key, e) {
var a = new Date(e);
newdateobject.push(a.getFullYear()+'-'+(a.getMonth()+1) +'-'+a.getDate());
});
IF the format you mentioned is consistent, then:
date.forEach(function(d) {
d = d.substring(0, 10);
})

How to get the holidays date in my case?

I am trying to get the holidays of given range of dates.
For example:
var holiday = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'...other holidays elements ];
var startDate = '2014-08-01'
var endDate = '2014-12-30';
var holidays=getHolidays(startDate, endDate);
//console.log(holidays) -> output 2014-12-24 and 2014-12-25.
getHolidays = function(startDate, endDate) {
var holidays=[];
//not sure how to get holidays here....
return holidays
}
I was hoping to write a function to get 2014-12-24 and 2014-12-25. My brain is fried now and I don't know what's the best approach on this. Can anyone help me about it? Thanks a lot!
The solution is to use filter function of array. The first parameter is the array you need to filter, and in your case, it's ['2014-01-01', '2014-07-04', '2014-12-24', '2014-12-25'].
var getHolidays = function(holiday,startDate, endDate) {
return holiday.filter(function(element){
var start = new Date(startDate);
var end = new Date(endDate);
var temp = new Date(element);
return temp >= start && temp <= end;
});
}
var holiday = ['2014-01-01', '2014-07-04', '2014-12-24', '2014-12-25'];
var startDate = '2014-08-01'
var endDate = '2014-12-30';
var holidays = getHolidays(holiday,startDate, endDate); //["2014-12-24", "2014-12-25"]
It works exactly as what you expect as shown in
JSFiddle
You could try turning them into date objects, and then comparing them that way. Something like:
var holidays = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'];
var startDate = '2014-08-01';
var endDate = '2014-12-30';
var getHolidays = function(startDate, endDate) {
var startTime = new Date(startDate).getTime();
var endTime = new Date(endDate).getTime();
var output = [];
holidays.forEach(function(holiday) {
var holidayTime = new Date(holiday).getTime();
if (holidayTime >= startTime && holidayTime <= endTime) {
output.push(holiday);
}
});
return output;
}
var holidays = getHolidays(startDate, endDate);
console.log(holidays);
As plain strings, the getHolidays function can be:
// Get holidays between two dates
function getHolidays(startDate, endDate) {
var output = [];
var i = 0;
var holiday;
while ((holiday = holidays[i++]) && holiday < endDate) {
if (startDate <= holiday) {
output.push(holiday)
}
}
return output;
}
If you are using ISO 8601 date strings, there's no need to convert them to Date objects. One of the reasons for the ISO format is that in most systems, you can compare strings directly rather than Date objects or some number value.
You can also parse the strings to Date objects, then use those to do the calculations but it takes more code for no real benefit:
// Parse date string in y-m-d format
function parseYMD(s) {
var b = s.split(/\D/);
var d = new Date();
d.setHours(0,0,0,0);
d.setFullYear(b[0], --b[1], b[2]);
return d.getFullYear() == b[0] && d.getDate() == b[2]? d : NaN;
}
// Holiday array
var holidays = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'];
// Get holidays between two dates
function getHolidays(startDate, endDate) {
startDate = parseYMD(startDate);
endDate = parseYMD(endDate);
var output = [];
var i = 0;
var holiday;
for (var i=0, iLen=holidays.length; i<iLen; i++) {
holiday = parseYMD(holidays[i]);
if (holiday <= endDate) {
if (holiday >= startDate) {
output.push(holidays[i]);
}
}
}
return output;
}
console.log(getHolidays('2014-08-01', '2014-12-30')); // ["2014-12-24", "2014-12-25"]

Categories