Loop through a date range with JavaScript - javascript

Given two Date() objects, where one is less than the other, how do I loop every day between the dates?
for(loopDate = startDate; loopDate < endDate; loopDate += 1)
{
}
Would this sort of loop work? But how can I add one day to the loop counter?
Thanks!

Here's a way to do it by making use of the way adding one day causes the date to roll over to the next month if necessary, and without messing around with milliseconds. Daylight savings aren't an issue either.
var now = new Date();
var daysOfYear = [];
for (var d = new Date(2012, 0, 1); d <= now; d.setDate(d.getDate() + 1)) {
daysOfYear.push(new Date(d));
}
Note that if you want to store the date, you'll need to make a new one (as above with new Date(d)), or else you'll end up with every stored date being the final value of d in the loop.

Based on Tom GullenĀ“s answer.
var start = new Date("02/05/2013");
var end = new Date("02/10/2013");
var loop = new Date(start);
while(loop <= end){
alert(loop);
var newDate = loop.setDate(loop.getDate() + 1);
loop = new Date(newDate);
}

I think I found an even simpler answer, if you allow yourself to use Moment.js:
// cycle through last five days, today included
// you could also cycle through any dates you want, mostly for
// making this snippet not time aware
const currentMoment = moment().subtract(4, 'days');
const endMoment = moment().add(1, 'days');
while (currentMoment.isBefore(endMoment, 'day')) {
console.log(`Loop at ${currentMoment.format('YYYY-MM-DD')}`);
currentMoment.add(1, 'days');
}
<script src="https://cdn.jsdelivr.net/npm/moment#2/moment.min.js"></script>

If startDate and endDate are indeed date objects you could convert them to number of milliseconds since midnight Jan 1, 1970, like this:
var startTime = startDate.getTime(), endTime = endDate.getTime();
Then you could loop from one to another incrementing loopTime by 86400000 (1000*60*60*24) - number of milliseconds in one day:
for(loopTime = startTime; loopTime < endTime; loopTime += 86400000)
{
var loopDay=new Date(loopTime)
//use loopDay as you wish
}

Here simple working code, worked for me
var from = new Date(2012,0,1);
var to = new Date(2012,1,20);
// loop for every day
for (var day = from; day <= to; day.setDate(day.getDate() + 1)) {
// your day is here
console.log(day)
}

var start = new Date("2014-05-01"); //yyyy-mm-dd
var end = new Date("2014-05-05"); //yyyy-mm-dd
while(start <= end){
var mm = ((start.getMonth()+1)>=10)?(start.getMonth()+1):'0'+(start.getMonth()+1);
var dd = ((start.getDate())>=10)? (start.getDate()) : '0' + (start.getDate());
var yyyy = start.getFullYear();
var date = dd+"/"+mm+"/"+yyyy; //yyyy-mm-dd
alert(date);
start = new Date(start.setDate(start.getDate() + 1)); //date increase by 1
}

As a function,
function getDatesFromDateRange(from, to) {
const dates = [];
for (let date = from; date <= to; date.setDate(date.getDate() + 1)) {
const cloned = new Date(date.valueOf());
dates.push(cloned);
}
return dates;
}
const start = new Date(2019, 11, 31);
const end = new Date(2020, 1, 1);
const datesArray = getDatesFromDateRange(start, end);
console.dir(datesArray);

Based on Tabare's Answer,
I had to add one more day at the end, since the cycle is cut before
var start = new Date("02/05/2013");
var end = new Date("02/10/2013");
var newend = end.setDate(end.getDate()+1);
var end = new Date(newend);
while(start < end){
alert(start);
var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
}

Didn't want to store the result in an array, so maybe using yield?
/**
* #param {object} params
* #param {Date} params.from
* #param {Date} params.to
* #param {number | undefined} params.incrementBy
* #yields {Date}
*/
function* iterateDate(params) {
const increaseBy = Math.abs(params.incrementBy ?? 1);
for(let current = params.from; current.getTime() <= params.to.getTime(); current.setDate(current.getDate() + increaseBy)) {
yield new Date(current);
}
}
for (const d of iterateDate({from: new Date(2021,0,1), to: new Date(2021,0,31), incrementBy: 1})) {
console.log(d.toISOString());
}

If you want an efficient way with milliseconds:
var daysOfYear = [];
for (var d = begin; d <= end; d = d + 86400000) {
daysOfYear.push(new Date(d));
}

Let us assume you got the start date and end date from the UI and stored it in the scope variable in the controller.
Then declare an array which will get reset on every function call so that on the next call for the function the new data can be stored.
var dayLabel = [];
Remember to use new Date(your starting variable) because if you dont use the new date and directly assign it to variable the setDate function will change the origional variable value in each iteration`
for (var d = new Date($scope.startDate); d <= $scope.endDate; d.setDate(d.getDate() + 1)) {
dayLabel.push(new Date(d));
}

Based on Jayarjo's answer:
var loopDate = new Date();
loopDate.setTime(datFrom.valueOf());
while (loopDate.valueOf() < datTo.valueOf() + 86400000) {
alert(loopDay);
loopDate.setTime(loopDate.valueOf() + 86400000);
}

Related

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);
});

Array of days in between months

I have two dates: Startdate and enddate
startdate = "10/10/2018" enddate = "03/09/2019"
I am trying to create an array of dates between those 2 dates. I have the following code.
function getDateArray (start, end) {
var arr = [];
var startDate = new Date(start);
var endDate = new Date(end);
endDate.setMonth( endDate.getMonth());
while (startDate <= endDate) {
arr.push(new Date(startDate));
startDate.setMonth(startDate.getMonth() + 1);
}
return arr;
}
Then calculate the number of days between those months in between.
10/10/2018 to 11/10/2018 = 30 days
11/10/2019 to 12/10/2018 = 30 days or so depending on number of days between the 2 dates and then create an array of the dates.
[30,30,31....till end date]
function daysBetween(date1, date2 )
{
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var dayDifference = Math.ceil(timeDiff / (1000 * 3600 * 24));
return dayDifference;
}
I tried the following code and it's returning the array of number of dates however, it's not accurate. It keeps returning 32 days in October. The output it's giving right now is as follows. I am not sure what i am doing wrong here but it looks like it's only going till February and displaying the result.
Any help will be appreciated. Thank you.
Output: [32,30,31,31,28]
var dateArr = getDateArray(z, y);
console.log(dateArr);
var dayCounts = "";
for (var x = 0; x < dateArr.length-1; x++)
{
dayCounts += daysBetween(dateArr[x], dateArr[x+1]);
}
console.log("datearrlength" + dateArr.length);
console.log(dayCounts);
i think this will work for you,
Date.prototype.addDay= function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
function getDateBwStartandEnd(sdate, edate) {
var dateArray = new Array();
var currentDate = sdate;
while (currentDate <= edate) {
dateArray.push(new Date (currentDate));
currentDate = currentDate.addDay(1);
}
return dateArray;
}
** Shamelessly copied from web, but this works fine for me.
While the following doesn't answer your question it is an alternative approach to the overall problem you are attempting to solve.
One approach would be to simply get the time difference between the two dates and then divide by the number of microseconds in a day. As you will notice though it is not exact and so a floor is used to get the days. There are other concerns with this approach as well such as date ranges before the epoch but it is a very simplistic approach and might work depending on your needs.
const startDate = '10/10/2018';
const endDate = '03/09/2019';
const start = (new Date(startDate)).valueOf();
const end = (new Date(endDate)).valueOf();
const timeBetween = end - start;
console.log({timeBetween, days: Math.floor(timeBetween/86400000)});
A slightly more robust is to essentially use a counter that increments itself by adding 1 day to the counter and the start date while the start date is less than the end date. Again, there are some concerns with this approach but that also depends on your needs.
const startDate = '10/10/2018';
const endDate = '03/09/2019';
let start = new Date(startDate);
const end = (new Date(endDate)).valueOf();
let daysBetween = 0;
while (start.valueOf() < end) {
daysBetween++;
start.setDate(start.getDate() + 1);
}
console.log(daysBetween);
Finally, a more robust solution to avoid the variety of issues with manipulating and working with dates is to use a library like momentjs. Using its difference method would look like the following.
const start = moment([2018, 10, 10]);
const end = moment([2019, 3, 9]);
console.log(end.diff(start, 'days'));
<script src="http://momentjs.com/downloads/moment.min.js"></script>
Using the following code worked for me. I added 1 extra month to my end date and it gives the proper date range. Also, instead of Math.ceil, i used Math.round and it gives the right number of date.
function getDateArray (start, end) {
var arr = [];
var startDate = new Date(start);
var endDate = new Date(end);
endDate.setMonth( endDate.getMonth());
while (startDate <= endDate) {
arr.push(new Date(startDate));
startDate.setMonth(startDate.getMonth() + 1);
}
return arr;
}

HOW do I creating an array of dates between a start and end date?

I want to create a list of dates starting from 2014/0/1 to 2020/11/31 (dates are represented in JavaScript).
This is the code
var initialTime = new Date(2014, 0, 1);
var endTime = new Date( 2050, 11, 31);
var arrTime = [];
arrTime.push(initialTime);
if( initialTime < endTime) {
for( var q = initialTime; q <= endTime; q.setDate(q.getDate() + 1)) {
arrTime.push(q);
}
}
document.querySelector("#Time").innerHTML = arrTime;
This is what the code returns. It is just a list of " Sun Jan 01 2051 00:00:00 GMT-0500 (EST)." How do I correct this?
When you do q.setTime( ... ) you are modifying the Date object itself. You are pushing the same object into the array at each iteration, hence modifying it modifies the entire array.
If you only want the string representations of the dates only, you can do:
let initialTime = new Date("2018-03-09Z08:00:00")
,endTime = new Date("2018-03-14Z08:00:00")
,arrTime = []
;
for (let q = initialTime; q <= endTime; q.setDate(q.getDate() + 1)) {
arrTime.push(q.toString());
}
console.log(arrTime);
Or, if you want to have an array of actual Date instances:
let initialTime = new Date("2018-03-09Z08:00:00")
,endTime = new Date("2018-03-14Z08:00:00")
,arrTime = []
,dayMillisec = 24 * 60 * 60 * 1000
;
for (let q = initialTime; q <= endTime; q = new Date(q.getTime() + dayMillisec)) {
arrTime.push(q);
}
console.log(arrTime);
first of all you can not compare two dates using ==
second problem is you need to create a new Date object each time you push one to the array ex. .push(new Date(q.getTime())
the next problem is you aren't properly adding a day to the last day each time before you push into the array
do something like
pseudo code ---
var dates = [];
while( firstDate < secondDate ){
// this line modifies the original firstDate reference which you want to make the while loop work
firstDate.setDate(firstDate.getDate() + 1);
// this pushes a new date , if you were to push firstDate then you will keep updating every item in the array
dates.push(new Date(firstDate);
}
You are pushing the same memory reference to the array, hence the changes you make affect all of them.
Try:
var copiedDate = new Date(q.getTime());
arrTime.push(copiedDate);
This way you are always pushing a new object.
var resolution = 1000, // Number of dates to capture between start and end
results = [], // will be populated with the for loop
start = Date.now(), // Set to whatever you want
end = start + (1000 * 60 * 60 * 24), // Set to what ever you want
delta = end - start
for (let i = 0; i < resolution; i++) {
let t = (delta / resolution) * i
results.push(new Date(start + t))
}
console.log(results)
live example: https://jsfiddle.net/5ju7ak75/1/
Short ES6 solution:
const getDatesInRange = (min, max) => Array((max-min)/86400000).fill(0).map((_, i) => new Date((new Date()).setDate(min.getDate() + i)))
Example
getDatesInRange(new Date('12-25-2000'), new Date('12-25-2001'))

How to count the number of sundays between two dates

I tried the JS below:
var start = new Date("25-05-2016");
var finish = new Date("31-05-2016");
var dayMilliseconds = 1000 * 60 * 60 * 24;
var weekendDays = 0;
while (start <= finish) {
var day = start.getDay()
if (day == 0) {
weekendDays++;
}
start = new Date(+start + dayMilliseconds);
}
alert(weekendDays);
However, it gives the wrong output.
I need to get the total count of Sundays between the two dates.
You use incorrect date format.It will work if init date so:
var start = new Date("2016-05-25");
var finish = new Date("2016-05-31");
Your date format is wrong. Dates' string format is "yyyy-mm-dd". See here for more information.
Also, looping each day of the interval is very inefficient. You may try the following instead.
function getNumberOfWeekDays(start, end, dayNum){
// Sunday's num is 0 with Date.prototype.getDay.
dayNum = dayNum || 0;
// Calculate the number of days between start and end.
var daysInInterval = Math.ceil((end.getTime() - start.getTime()) / (1000 * 3600 * 24));
// Calculate the nb of days before the next target day (e.g. next Sunday after start).
var toNextTargetDay = (7 + dayNum - start.getDay()) % 7;
// Calculate the number of days from the first target day to the end.
var daysFromFirstTargetDay = Math.max(daysInInterval - toNextTargetDay, 0);
// Calculate the number of weeks (even partial) from the first target day to the end.
return Math.ceil(daysFromFirstTargetDay / 7);
}
var start = new Date("2016-05-25");
var finish = new Date("2016-05-31");
console.log("Start:", start);
console.log("Start's week day num:", start.getDay());
console.log("Finish:", finish);
console.log("Finish's week day num:", finish.getDay());
console.log("Number of Sundays:", getNumberOfWeekDays(start, finish));
Your date format and comparison condition should change like the following:
var start = new Date("2016-05-11");
var finish = new Date("2016-05-31");
var dayMilliseconds = 1000 * 60 * 60 * 24;
var weekendDays = 0;
while (start.getTime() <= finish.getTime()) {
var day = start.getDay();
if (day == 0) {
weekendDays++;
}
start = new Date(+start + dayMilliseconds);
}
alert(weekendDays);
Check Fiddle
You are using incorrect date format.
Just Change the format to:
var start = new Date(2016, 4, 25);
var finish = new Date(2016, 4, 31);
Try this function:
function CalculateWeekendDays(fromDate, toDate){
var weekendDayCount = 0;
while(fromDate < toDate){
fromDate.setDate(fromDate.getDate() + 1);
if(fromDate.getDay() === 0){
++weekendDayCount ;
}
}
return weekendDayCount ;
}
console.log(CalculateWeekendDays(new Date(2011, 6, 2), new Date(2011, 7, 2)));
This will give you number of sunday come between 2 dates
change your date format.It will work
var start = new Date("05-16-2016");
var finish = new Date("05-31-2016");
var dayMilliseconds = 1000 * 60 * 60 * 24;
var weekendDays = 0;
while (start <= finish) {
var day = start.getDay()
if (day == 0) {
weekendDays++;
}
start = new Date(+start + dayMilliseconds);
}
console.log(weekendDays);
JS date format doesn't have "dd-MM-yyyy" ,so it will invalid date format .Try recreate date is ok or just change your date format Date Format
Try this:
var start = new Date("25-05-2016");
var end = new Date("31-05-2016");
var startDate = new Date(start);
var endDate = new Date(end);
var totalSundays = 0;
for (var i = startDate; i <= endDate; ){
if (i.getDay() == 0){
totalSundays++;
}
i.setTime(i.getTime() + 1000*60*60*24);
}
console.log(totalSundays);
// Find date of sundays b/w two dates
var fromDate = new Date('2022-10-26')
var toDate = new Date('2022-11-31')
var sunday = 0
var milisec = 1000 * 60 * 60 * 24;
while (fromDate <= toDate) {
var day = fromDate.getDay()
if (day == 0) {
sunday++
console.log('Date of sunday:', fromDate)
}
fromDate = new Date(+fromDate + milisec)
}
console.log('Total no. of sundays:', sunday)

Get Month as well as date in my variable - javascript

Hi i am trying to do a IF statement which allows the current date to be compared to the input date.. if the input date is below the current date it will be false.
I have got the date passing through my variable but it only stores the number so for example it compares day 9 to another day, which is not very reliable. I want the variable to take in the month and the year as well, meaning it can compare the ENTIRE DATE.
If there is a better way let me know.
Here is my code
if (this.element.find('#visitdate').length > 0) {
var dateParts = $('#visitdate').val().split('/');
var check = new Date(dateParts[2], dateParts[1], dateParts[0], 0,0,0,0).getDate();
var today = new Date().getDate;
if (check < today) {
_errMsg = "Please enter a furture visit date";
return false;
} else {
return true;
}
}
Your line for today's date contains an error:
var today = new Date().getDate;
should be
var today = new Date().getDate();
format as mm/dd/yyyy
var from = '08/19/2013 00:00'
var to = '08/12/2013 00:00 '
var today = new Date().getDate();
function isFromBiggerThanTo(dtmfrom, dtmto){
var from = new Date(dtmfrom).getTime();
var to = new Date(dtmto).getTime() ;
return from >= to ;
}
or using below
var x = new Date('2013-05-23');
var y = new Date('2013-05-23');
and compare
You can try this - it's working fine in my project -
Step 1
First Create javascript function as below.
Date.prototype.DaysBetween = function () {
var intMilDay = 24 * 60 * 60 * 1000;
var intMilDif = arguments[0] - this;
var intDays = Math.floor(intMilDif / intMilDay);
if (intDays.toLocaleString() == "NaN") {
return 0;
}
else {
return intDays + 1;
}
}
Step 2
-
var check = new Date(dateParts[2], dateParts[1], dateParts[0], 0,0,0,0).getDate();
var today = new Date().getDate;
var dateDiff = check .DaysBetween(today);
// it will return integer value (difference between two dates )
if(dateDiff > 0 ){ alert('Your message.......');}
You can have this much easier.
You dont need to check with getDate() property you can just compare 2 dates.
And also is not needed to initialize with hours, minutes and seconds the Date, you only need year, month and date.
Here you have your example simplified
var dateParts = $('#visitdate').val().split('/');
var check = new Date(dateParts[2], dateParts[1], dateParts[0]);
var today = new Date();
if (check < today) {
return false;
} else {
return true;
}
http://jsfiddle.net/wns3LkLv/
Try this:
var user="09/09/2014/5/30";
var arrdt= user.split("/");
var userdt = new Date(arrdt[2], arrdt[1] - 1, arrdt[0],arrdt[3],arrdt[4]);
var currdt = new Date();
if (userdt < currdt) {
alert("userdate is before current date"); //do something
}else{
alert("userdate is after current date"); //do something
}
Thanks for all your answers guys i have fixed it.
I used the getTime function instead of getDate.
Then the check variable had to have a -1 assigned to the month as it was going 1 month to high.
var check = new Date(dateParts[2], dateParts[1]-1, dateParts[0], 0,0,0,0).getTime();
Cheers

Categories