I have the following code which I want to return an incremental date for the next 10 days
const startingDay = new Date('2021-10-29');
const thisDay = new Date(startingDay);
for(var i=1; i<10; i++) {
thisDay.setDate(startingDay.getDate() + i);
console.log(thisDay);
}
which is great, but for some reason as soon as it hits Oct 31, it starts going up in months rather than days.
Why would that be?
Thanks
Altering your logic slightly will give you the desired behaviour, setDate() will not work the way you expect with multiple calls to the same date instance.
The reason is that, starting with November 01, at iteration #4, we'll be setting the date to 33 (29 + 4). The logic used by setDate will be to advance the date to the next month, December, since November has only 30 days, then advancing another 2 days to December 3. The same effect will happen for subsequent iterations.
By re-creating the thisDay variable on each iteration, the logic used by setDate will work as expected.
const startingDay = new Date('2021-10-29');
for(var i= 1; i < 10; i++) {
let thisDay = new Date(startingDay);
thisDay.setDate(startingDay.getDate() + i);
console.log(thisDay);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
for(var i=1; i<10; i++) {
thisDay.setDate(startingDay.getDate() + i);
Since you're looping from 1 to i < 10, you'll add more days as the loop progresses.
I want to return an incremental date for the next 10 days
So why update thisDay with the startingDay.getDate() + i if you can just use thisDay.getDate() + 1:
const startingDay = new Date('2021-10-29');
const thisDay = new Date(startingDay);
for(var i=1; i<10; i++) {
thisDay.setDate(thisDay.getDate() + 1);
console.log(thisDay);
}
"2021-10-30T00:00:00.000Z"
"2021-10-31T00:00:00.000Z"
"2021-11-01T01:00:00.000Z"
"2021-11-02T01:00:00.000Z"
"2021-11-03T01:00:00.000Z"
"2021-11-04T01:00:00.000Z"
"2021-11-05T01:00:00.000Z"
"2021-11-06T01:00:00.000Z"
"2021-11-07T01:00:00.000Z"
Read the docs for https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate .
It will automatically switch to the next or previous month if you provide a value that is out of range for the current month. This makes it easier to jump between months when adding days.
But the way you've coded your example, you always start from the day of the original date, but edit the second date:
i:1 | date = 2021-10-29 -> set day to 30th -> date = 2021-10-30
i:2 | date = 2021-10-30 -> set day to 31st -> date = 2021-10-31
i:3 | date = 2021-10-31 -> set day to 32nd -> date = 2021-11-01, since oct only has 31 days
i:4 | date = 2021-11-01 -> set day to 33rd -> date = 2021-12-03, since nov has 30 days, so adding 33 days to the first of nov, gives us 3rd of december
To avoid the incorrect day due to month switching you can solve it using Date() itself.
const startingDay = new Date('2021-10-29');
let thisDay = new Date(startingDay);
for(let i = 1; i<10; i++) {
thisDay = new Date(Date.now() + i * 24 * 60 * 60 * 1000);
console.log(thisDay.getDate());
}
Related
I am trying to run a for loop that has to loop 8 times. On each iteration I want the loop to increment the value by +1 hour.
The final output should be in this time format:
opening hours:
08:00, 09:00, 10:00,11:00, 12:00, 13:00, 14:00, 15:00,16:00
In this case timediff mentioned in the for...loop holds the value of 8.
var minutesToAdd = 60;
var currentDate = new Date("2022-04-10 08:00:00");
var futureDate = new Date(currentDate.getTime() + minutesToAdd * 120000).toLocaleTimeString();
for (let i = 0; i < timeDiff; i++) {
console.log(futureDate, 'futureeee date');
}
Your code never updates futureDate in the loop. Also, when you expect to print 08:00 in the example, you should print currentDate when no minutes have been added yet.
I would also suggest you use the native function setMinutes and getMinutes to add a number of minutes to a date object.
You say that timeDiff has a value of 8, but then you say you want 9 outputs (8:00 ... 16:00), so you'll need an additional iteration.
Finally, to get the hh:mm output format, there are several solutions. One is to choose a locale that uses a format that is close to what you need, and express you want the short format (without seconds):
let timeDiff = 9; // One more to also output 16:00
let minutesToAdd = 60;
let currentDate = new Date("2022-04-10 08:00:00");
for (let i = 0; i < timeDiff; i++) {
console.log(currentDate.toLocaleTimeString("en-SE", { timeStyle: "short" }));
currentDate.setMinutes(currentDate.getMinutes() + minutesToAdd);
}
You can then use a simple for-loop to iterate from 0 up to and including timeDiff, incrementing each iteration by 1.
for (let hours = 0; hours <= timeDiff; hours += 1) {
// ...
}
Instead of a starting date we'll start with a timestamp Date.parse("2022-04-10 08:00:00"). This allows us to add the time from the loop to the timestamp and create a new date.
const date = new Date(currentTimestamp + hours*HOURS);
To only display the time I've taken the liberty of using the solution provided by the answer of trincot.
const MILLISECOND = 1 , MILLISECONDS = MILLISECOND;
const SECOND = 1000*MILLISECONDS, SECONDS = SECOND ;
const MINUTE = 60*SECONDS , MINUTES = MINUTE ;
const HOUR = 60*MINUTES , HOURS = HOUR ;
const timeDiff = 8;
var currentTimestamp = Date.parse("2022-04-10 08:00:00");
for (let hours = 0; hours <= timeDiff; hours += 1) {
const date = new Date(currentTimestamp + hours*HOURS);
console.log(date.toLocaleString(undefined, { timeStyle: "short" }));
}
I need to get the next 4 Thursdays with javascript, and append the result into a select box but if the current date is past Sunday, don't get the first Thursday (start a week later).
So for example:
Current date = Saturday 12th June 2021
Get Next 4 Thursdays: 17th June 2021, 24th June 2021, 1st July 2021, 8th July 2021.
Current Date = Tuesday 15th June 2021 -- Don't get 17th June 2021, so list would be:
24th June 2021, 1st July 2021, 8th July 2021, 15th July 2021.
I had some code originally that would get the thursdays for X amount of months, but this isn't quite what I want, as it gets all thursdays in one month, rather than the next 4 thursdays. I'm guessing I can reuse the get day of the week code, and modify it to just get the next 4 days... then somehow filter if the date is past Sunday?
function getNextMonths(num) {
let current = new Date();
let months = [];
for (let i = 0; i <= num; i++) {
let next = new Date();
next.setDate(1); // First day...
next.setMonth(current.getMonth() + i); //...of next month
months.push(next);
}
return months;
}
function getDayOfWeek(num_week_day, dates) {
let days = [];
var today = new Date();
for (let i = 0; i < dates.length; i++) {
// Evaluate current month
let current = {
year: dates[i].getFullYear(),
month: dates[i].getMonth()
};
current.days = new Date(current.year, current.month + 1, 0).getDate();
// Loop & evaluate days
for (let d = 1; d <= current.days; d++) {
let date = new Date(current.year, current.month, d);
if (date.getDay() == num_week_day) {
if(date.getTime() > today.getTime()){
days.push(date);
}
}
}
}
return days;
}
//Convert to Nice looking Date
function dateToString(date){
return date.toLocaleDateString("en-GB", {
dateStyle: 'full'
});
}
//Output date as mm/dd/yyyy for ouput value
function dateToValue(date){
return date.toLocaleDateString("en-GB", {
year: "numeric",
month: "short",
day: "numeric",
});
}
// Get all Thursdays (4th day of the week) within the next 2 months.
var select = document.getElementById("arr");
var elmts = getDayOfWeek(4, getNextMonths(1));
// Main function
jQuery( document ).ready(function() {
jQuery('#sub_start_date').find('option').remove();
jQuery.each(elmts, function(i, p) {
jQuery('#sub_start_date').append(jQuery('<option></option>')
.val(dateToValue(p)).html(dateToString(p)));
});
});
In my eyes your code is incomplete so I cannot run in my own enviroment. My suggestion for you is though quite simple:
You store your dates in an array elmts and you loop through it to create all option elements.
My suggestion is:
Create always five dates
Depends on the daynumber remove the first or the last entry from array elmts.
Javascript offers two methods for it:
The method .shift() removes the first element from an array (see also https://www.w3schools.com/jsref/jsref_shift.asp ).
The method .pop() removes the last element from an array (see also https://www.w3schools.com/jsref/jsref_pop.asp ).
Based on https://gomakethings.com/how-to-get-the-date-for-a-specific-day-of-the-week-with-vanilla-js/
My code:
/* Some nassecary preconditions */
var datebase = new Date();
var targetDaynumber = 4;
var currentDiff = new Date().getDay();
/* Calculates a timestamp based on your wished weekday */
var getNextDay = function (basedate) {
// The current day
var now = basedate.getDay();
var diff = targetDaynumber - now;
diff = diff < 1 ? 7 + diff : diff;
// Get the timestamp for the desired day
var nextDayTimestamp = basedate.getTime() + (1000 * 60 * 60 * 24 * diff);
// Get the next day
return new Date(nextDayTimestamp);
};
/* ------------------------------------------------- */
/* Creating five timestamps */
var dateArray = [];
var loopindex = 5;
for (x = 0; x < loopindex; x++)
{
datebase = getNextDay(datebase);
dateArray.push(datebase);
}
/* Calculating the timegap */
if (currentDiff <= targetDaynumber) {
//Timegap is too small, remove the earliest timestamp
dateArray.shift();
} else {
//Timegap is ok, the fith element is not nassecary
dateArray.pop();
}
I'm getting some strange results from adding hours to a date. I'm basically adding 0, 6, 12, 18, 24, 30, etc hours to a Javascript date. I came across some of the recommendations online (like this: Adding hours to Javascript Date object?), but when in a loop it was skipping ahead many hours/months. It seemed to be keeping the new version of the date and just adding hours to it...when I really just want to add the hours to the original date.
So, here's the basics of what I have.
for (var i = 1; i < 4; i++) {
hour_date.setHours(hour_date.getHours() + hour);
output.push(hour_date...)
}
//where hour is 6, 12, 18, 24, etc in a loop
//and where hour_date is defined earlier and is
//Sun Apr 02 2017 12:00:00 GMT-0700 (Pacific Daylight Time)
So I'm trying to figure out how to simply add 6 hours to an initial date variable...so I can push those values out to an array. I understand the push part...but I'm just trying to add the hours correctly within the loop.
Thanks very much for any help!
It may be simpler to use the date's raw value and add to it in milliseconds.
Example:
var date = Date.now()
console.log(new Date(date))
var date2 = new Date(date+1000*60*60*6) // Add 6 hours.
console.log(date2)
var date3 = new Date(date+1000*60*60*3) // Add 3 hours.
console.log(date3)
In a loop you'll have to make sure you create new variables from the original variable, not modifying the original. In your case this is easy if you simply create new Date objects and insert them into an array. Use .valueOf() to access the underlying number value of a date object.
var date = new Date();
dates = [date];
for(var i = 6; i <= 30; i += 6) {
dates.push(new Date(date.valueOf() + i * 1000 * 60 * 60));
}
console.log(JSON.stringify(dates, null, 4))
// [
// "2017-04-03T00:57:52.420Z",
// "2017-04-03T06:57:52.420Z",
// "2017-04-03T12:57:52.420Z",
// "2017-04-03T18:57:52.420Z",
// "2017-04-04T00:57:52.420Z",
// "2017-04-04T06:57:52.420Z"
// ]
You need a new object each time. Currently you are modifying the same object over and over and pushing the same reference to each index of the array
Try:
for (var i= 1; i < 4; i++) {
var newDate = new Date(hour_date);
hour += 6;
newDate.setHours(hour_date.getHours() + hour);
output.push(newDate);
}
var hour_date = new Date(), output = [], hour = 0;
for (var i = 1; i < 10; i++) {
var newDate = new Date(hour_date);
hour += 6;
newDate.setHours(hour_date.getHours() + hour);
output.push(newDate);
}
console.log(JSON.stringify(output, null, ' '))
try this instead;
let hours = [6, 12, 18, 24];
let hour_date = new Date;
hours = hours.map(hour=>{
return new Date(hour_date.getTime() + (hour*60*60*1000))
});
console.log(hours);
I'm trying to make a function to get all the days of the week given the current day. I had a function that i thought was working until i noticed that if the day of the week is near the end of the month, like for example February, i get weird data. Anyone know whats going on and how to fix it?
function days(current) {
var week = new Array();
// Starting Monday not Sunday
var first = ((current.getDate() - current.getDay()) + 1);
for (var i = 0; i < 7; i++) {
week.push(
new Date(current.setDate(first++))
);
}
return week;
}
var input = new Date(2017, 1, 27);
console.log('input: %s', input);
var result = days(input);
console.log(result.map(d => d.toString()));
.as-console-wrapper{min-height:100%}
If you don't want to use some kind of other library like Moment.js you can also change your function a little and then it will work. Try this:
function dates(current) {
var week= new Array();
// Starting Monday not Sunday
current.setDate((current.getDate() - current.getDay() +1));
for (var i = 0; i < 7; i++) {
week.push(
new Date(current)
);
current.setDate(current.getDate() +1);
}
return week;
}
console.log(dates(new Date(2017, 1, 27)));
You can use Moment.js library - utility library for dates/time operations
Here's examplary code to get current week's dates starting from monday:
function getThisWeekDates() {
var weekDates= [];
for (var i = 1; i <= 7; i++) {
weekDates.push(moment().day(i));
}
return weekDates;
}
var thisWeekDates = getThisWeekDates();
thisWeekDates.forEach(function(date){ console.log(date.format());});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>
The code above prints following results to the console:
2017-03-20T21:26:27+01:00
2017-03-21T21:26:27+01:00
2017-03-22T21:26:27+01:00
2017-03-23T21:26:27+01:00
2017-03-24T21:26:27+01:00
2017-03-25T21:26:27+01:00
2017-03-26T21:26:27+02:00
I will trace your code using your example of Feb 27, 2017:
first = 27 - 1 + 1 = 27
loop:
Feb.setDate(27) = 27 feb
Feb.setDate(28) = 28 feb
Feb.setDate(29) = Not 29 days in Feb. So it sets current to 29-28 = 1st day of March
March.setDate(30) = March 30
March.setDate(31) = March 31
March.setDate(32) = Not 32 days in March. So it sets current to 31-32 = 1st of April..
April.setDate(33) = Not 33 days in April. So it sets current day 33-30 = 3rd day of May.
Please note that I used the shorthand of Month.setDate() to show the month of the current Date object when it was being called.
So the issue is with your understanding of setDate that is being used on current. It changes the month and if the value you use isn't a day in the month it adjusts the month and day appropriately. I hope this cleared things up for you.
For how to add one to a date, see Add +1 to current date. Adapted to your code, you can set current to the first day of the week then just keep adding 1 day and pushing copies to the array:
function days(current) {
var week = [];
// Starting Monday not Sunday
var first = current.getDate() - current.getDay() + 1;
current.setDate(first);
for (var i = 0; i < 7; i++) {
week.push(new Date(+current));
current.setDate(current.getDate()+1);
}
return week;
}
var input = new Date(2017, 1, 27);
console.log('input: %s', input);
var result = days(input);
console.log(result.map(d => d.toString()));
Note that this changes the date passed in (per the original code), you may want to make current a copy to avoid that.
Suppose monday starts the week, you can calculate monday and go to sunday. getDategives you the day of the week, and Sunday starts at 0. With momnday, we get just offset forward to 6 days to get sunday
mondayThisWeek(date: Date): Date {
const d = new Date(date)
const day = d.getDay()
const diff = d.getDate() - day + (day === 0 ? -6 : 1)
return new Date(d.setDate(diff))
}
const offsetDate = (base: Date, count: number): Date => {
const date = new Date(base)
date.setDate(base.getDate() + count)
return date
}
thisWeek(today: Date): TimeRange {
const monday = mondayThisWeek(today)
return {
startDate: monday,
endDate: offsetDate(monday, 6)
}
}
This can be achieved easly using moment
const getWeekDates = () => {
let weekDates = [];
for (let i = 0; i < 7; i++)
weekDates.push(moment().add(i, 'd'));
return weekDates;
};
console.log(getWeekDates());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>
(first, sorry for my bad english, i'm a beginner)
I have a chart of percent by date. I would like to display every day of the current week in the x-axis.
So, i tried to find how to get the seven days of the week.
that's what i have :
var curr = new Date; // get current date
var first = curr.getDate() - curr.getDay();//to set first day on monday, not on sunday, first+1 :
var firstday = (new Date(curr.setDate(first+1))).toString();
for(var i = 1;i<7;i++){
var next = first + i;
var nextday = (new Date(curr.setDate(next))).toString();
alert(nextday);
}
the alert begins well...until the end of the month. That's what i got :
1 : "Mon 27 Feb 2012 ..."
2 : "Tue 28 Feb 2012 ..."
3 : "Wed 29 Feb 2012 ..."
4 : "Thu 01 Mar 2012 ..."
5 : "Sat 31 Mar 2012 ..."
6 : "Sun 01 Apr 2012 ..."
So, as you can see, it switches the friday and... strangely it switch to the good date...4 weeks later...
So, do you have a better solution for me, or maybe you could just help me and say what is the problem.
Thank you!
I'm afraid you have fallen into one of the numerous traps of object mutation. :)
The problem is that, in the line "var nextday = ...", you are changing the date saved in "curr" on every iteration by calling setDate(). That is no problem as long as next is within the range of the current month; curr.setDate(next) is equivalent to going forward one in this case.
The problems begin when next reaches 30. There is no February 30, so setDate() wraps around to the next month, yielding the 1st of March - so far so good. Unfortunately, the next iteration calls curr.setDate(31), and as curr is the 1st of March (remember that the object referenced by curr is changed in each iteration), we get... March 31! The other strange values can be explained the same way.
A way to fix this is to copy curr on each iteration and then call setDate(), like so:
for (var i = 1; i < 7; i++) {
var next = new Date(curr.getTime());
next.setDate(first + i);
alert(next.toString());
}
Thank you all,
I understood that everytime i change the curr value and that was the problem.
All your solutions are working, but i'll prefer the simplest one, the one from #denisw, which I copy there for anybody else with the same problem :
var curr = new Date; // get current date
var first = curr.getDate() - curr.getDay();
var firstday = (new Date(curr.setDate(first+1))).toString();
for(var i = 1; i < 7; i++) {
var next = new Date(curr.getTime());
next.setDate(first+i);
alert(next.toString());
}
Once again, thank you all, for your quick answers and your help!
You can add date and day. The former goes from 1 to 28..31 and the latter from 0 to 6. What should the Date type do if you set the date to -3?
The solution is to convert all values to milliseconds.
var ONE_DAY_IN_MILLIS = 1000*60*60*24;
var curr = new Date();
// Get offset to first day of week
// Note: Depending on your locale, 0 can be Sunday or Monday.
var offset = curr.getDay() * ONE_DAY_IN_MILLIS;
// Date at the start of week; note that hours, minutes and seconds are != 0
var start = new Date( curr.getTime() - offset );
for( var i=0; i<7; i++ ) {
var nextDay = new Date( start.getTime() + ( i * ONE_DAY_IN_MILLIS ) );
...
}
The problem is that you are modifying your curr date and creating a new date at the same time. There are two ways to do this:
Either never modifiy your curr date object and create new Dates:
var msInDay = 1000 * 60 * 60 * 24;
function addDays(date, days) {
return new Date(date.getTime() + days * msInDay);
}
var curr = new Date();
var first = addDays(curr, -curr.getDay() + 1);
alert(first);
for(var i = 1; i<7; i++) {
var next = addDays(first, i);
alert(next);
}
Or modify your curr date object consistently:
var curr = new Date();
curr.setDate(curr.getDate() - curr.getDay() + 1);
alert(curr);
for(var i = 1; i<7; i++) {
curr.setDate(curr.getDate() + 1);
alert(curr);
}
let curr = new Date;
let week = []
for (let i = 1; i <= 7; i++) {
let first = curr.getDate() - curr.getDay() + i
let day = new Date(curr.setDate(first)).toISOString().slice(0, 10)
week.push(day)
}
console.log('week:', week);
jsfidde: https://jsfiddle.net/sinh_nguyen/v9kszn2h/4/