Javascript Date Object giving out some unusual results [duplicate] - javascript

For m = range 1-12 it works as expected, increasing month by 1.
For m = range 13- it doesn't work as expected, increasing year by 1.
As m exceeds 12 inside loop I was expecting result:
Sun Feb 28 2015 00:00:00 GMT+0400 (GET)
Tue Mar 28 2015 00:00:00 GMT+0400 (GET)
Sat Apr 28 2015 00:00:00 GMT+0400 (GET)
Instead I get:
Sun Feb 28 2016 00:00:00 GMT+0400 (GET)
Tue Mar 28 2017 00:00:00 GMT+0400 (GET)
Sat Apr 28 2018 00:00:00 GMT+0400 (GET)
...
var loanAmount = 3800,
loanInterest = 32, // %
loanDuration = 48, // Month
loanGrace = 0,
loanFee = 1, // %
loanInitMonth = 0,
loanInitDay = 28,
loanInitYear = 2014;
var loanStart = new Date(loanInitYear,loanInitMonth,loanInitDay);
for (var m = loanInitMonth; m < loanDuration; m++) {
var d = loanStart;
d.setMonth(m);
console.log(m);
console.log(d);
}
Jsfiddle
As setMonth description states:
If a parameter you specify is outside of the expected range, setMonth
attempts to update the date information in the Date object
accordingly. For example, if you use 15 for monthValue, the year will
be incremented by 1 (year + 1), and 3 will be used for month.
I'm obviously not getting this behavior.
Browser Chrome.

When you do this, you are copying the reference to the Date object instead of creating a new copy of the object:
var d = loanStart;
Then, when you change the date in the d variable, you are also changing the date in the loanStart variable, as it's the same object.
Create a copy of the Date object:
var d = new Date(loanStart.getTime());

The problem is that you aren't adding the time to the original date, you're adding it to the current date. So setting the month > 12 to the current date will always add at least one year, which will increment the year.
You have two solutions:
Make sure you're always modifying the original date by maintaining a copy of that date.
Do real date math - trying to set the month (and rely on side-effects) when what you really want to do is increment the month makes for rather confusing code and will have edge cases when, for example, the day of the month isn't a valid day for that month.

Instead of passing m to setMonth, do d.setMonth(d.getMonth()+1) like below:
var loanAmount = 3800,
loanInterest = 32, // %
loanDuration = 48, // Month
loanGrace = 0,
loanFee = 1, // %
loanInitMonth = 0,
loanInitDay = 28,
loanInitYear = 2014;
var loanStart = new Date(loanInitYear,loanInitMonth,loanInitDay);
for (var m = loanInitMonth; m < loanDuration; m++) {
var d = loanStart;
d.setMonth(d.getMonth()+1);
console.log(m);
console.log(d);
}

Related

When you know what week it is, how to find out the start date of the week

Through the 'date-fns' module, I am receiving numbers of how many weeks the date is this year.
const current = '2022-03-10'
const weekNumber = getWeek(current, 1) // 11
On the contrary, if you only know the numbers, you want to know how to do the first date of the week number.
The way I want to know.
const weekNumber = 11;
const weekOfstartDate = anyFunc(weekNumber) // '2022-03-07'
Do you know the answer to this solution?
You can use the I token:
var dateFns = require("date-fns");
console.log(dateFns.parse('10','I', new Date()));
At npm.runkit.com that returns a date for Mon 7 Mar 2022. It seems date-fns assumes the year of the current week. I have no idea how to specify the year, attempting:
console.log(dateFns.parse('2022-10','YYYY-II', new Date(),{
useAdditionalWeekYearTokens: true
}));
Throws a range error: The format string mustn't contain YYYY and II at the same time. Similarly for "2022W10" and tokens "YYYY'W'II", it says Y and I tokens can't be in the same format string.
A function to do the same thing is:
// Returns the first day (Monday) of the specified week
// Year defaults to the current local calendar year
function getISOWeek(w, y = new Date().getFullYear()) {
let d = new Date(y, 0, 4);
d.setDate(d.getDate() - (d.getDay() || 7) + 1 + 7*(w - 1));
return d;
}
// Mon Mar 14 2022
console.log(getISOWeek(11).toString());
// Mon Jan 02 2023
console.log(getISOWeek(1,2023).toString());
// Mon Dec 28 2026
console.log(getISOWeek(53,2026).toString());
A robust function should validate the input such that the week number is 1 to 53 and that 53 is only permitted for years that have 53 weeks.
I wanted a solution only using date-fns functions. This is how i combined it:
const result = setWeek(nextMonday(new Date(year, 0, 4)), week, {
weekStartsOn: 1,
firstWeekContainsDate: 4,
});

Time difference giving positive value when it should be negative

To calculate the difference between now and a time X, I'm using the following:
var splitPickDate= startDate.split('/');
var splitPick = startTime.split(':');
var timeCalc = new Date(parseInt(splitPickDate[2]),parseInt(splitPickDate[0]),parseInt(splitPickDate[1]), parseInt(splitPick[0]), parseInt(splitPick[1]));
var now = new Date();
var diffNow = timeCalc - now;
Assuming splitPickDate = '01/28/2015', splitPick = '00:00' and now = Wed Jan 28 2015 15:35:04 GMT+0530 (India Standard Time) should I not get a negative value for diffNow?
Am I wrong in calculating the time difference between the two times?
I think thats because in JS when you use numbers for months January = 0, February = 1, etc.
Your code just uses 1 from the string which creates a date for 28 February, instead of 28 January. So you subtract a January time from a February time. Which is sure positive.
With this. your calculation will be ok for those particular dates:
var timeCalc = new Date(parseInt(splitPickDate[2]),parseInt(splitPickDate[0]),parseInt(splitPickDate[1]), parseInt(splitPick[0]), parseInt(splitPick[1]));

Working with Javascript dates, getting 0 or above 31

I am using this code to generate 5 dates for my 'calendar' from the current week:
var days = new Array(4);
GetDaysOfWeek(new Date());
function GetDaysOfWeek(date)
{
for (var i = 0; i < 5; i++)
{
var $dd = (date.getDate() - date.getDay() + 1 + i);
var $mm = date.getMonth()+1;
var $yyyy = date.getFullYear();
if($dd<10){$dd='0'+$dd}if($mm<10){$mm='0'+$mm}
days[i] = $dd+'/'+$mm+'/'+$yyyy;
}
}
However depending what date it is it can return 00/10/2013 or 32/10/2013 on some of my boxes. It seems the only one updating correct is the actual date I am on.
How would I update those 5 dates so I would get the correct dates instead of non exist dates.
Thanks in advance.
currentTimestamp = new Date().getTime()
currentDay = currentTimestamp-currentTimestamp%(24*60*60*1000)
for (var i = 1; i< 6; i++){
nextDay = new Date(currentDay + i*24*60*60*1000)
days[i] = nextDay.toString(); //specify the format yourself
}
Here's a somewhat shorter way of creating an array of the dates of 5 weekdays from a given date;
function weekdays(d){
// set date [d] (or today) to the sunday before
var d = (function(){
this.setDate(this.getDate()-(this.getDay()));
return this;
}).apply(d || new Date);
// create an Array with length 5 and map 5 dates starting
// from date [d] into it
return String(Array(5)).split(',')
.map(function(){
return new Date(this.setDate(this.getDate()+1));
}, d);
}
It returns the weekdays from the first monday before the date, or, if the given date is a sunday, the dates of the weekdays from the next week.
weekdays();
//=> [Mon Oct 21 2013 17:14:23 GMT+0200, ... ,Fri Oct 25 2013 17:14:23 GMT+0200]
weekdays(new Date('2013/10/06'));
//=> [Mon Oct 07 2013 00:00:00 GMT+0200, ..., Fri Oct 11 2013 00:00:00 GMT+0200]
See also: Mozilla DN on map
Maybe this jsfiddle is of use to you?

store date objects to array

I have two dates and want to save the days in between (plus start and end date) in an array
var date1 = new Date("Sep 23, 2013 12:00:00"); // Monday
var date2 = new Date("Sep 26, 2013 12:00:00"); // Thursday
var alldates = [];
for (var i=0; date1 <= date2; date1.setDate(date1.getDate() + 1), i++) {
alldates.push(date1);
}
alert(alldates.join('\n'));
With this code alert(alldates.join('\n')); shows the following
Fri Sep 27 2013 12:00:00 GMT+0200
Fri Sep 27 2013 12:00:00 GMT+0200
Fri Sep 27 2013 12:00:00 GMT+0200
Fri Sep 27 2013 12:00:00 GMT+0200
I am new to Javascript and want to get further understanding, so thank you for any explanation why the alert does not show
Mon Sep 23 2013 12:00:00 GMT+0200
Tue Sep 24 2013 12:00:00 GMT+0200
Wed Sep 25 2013 12:00:00 GMT+0200
Thu Sep 26 2013 12:00:00 GMT+0200
The problem you have is that you push references to the date1 object. When you change the date on it in your loop, you update the object, but all references still point to the same object.
You need to either push a text representation of your date, or a copy of your date1 object
for (var i=0; date1 <= date2; date1.setDate(date1.getDate() + 1), i++) {
alldates.push(new Date(date1));
}
alert(alldates.join('\n'));
As suggested, with a while loop
while( date1 <= date2 ) {
alldates.push(new Date(date1));
date1.setDate( date1.getDate() +1 );
}
Your array is storing the references for the single date object and everytime when setDate is called each of them are getting updated with new date value.
So it will be better to push the new date object in array like this,
var date1 = new Date("Sep 23, 2013 12:00:00"); // Monday
var date2 = new Date("Sep 26, 2013 12:00:00"); // Thursday
var alldates = [];
// pushing first date
alldates.push(new Date(date1.setDate(date1.getDate())));
for (var i=0; date1 <= date2; i++) {
alldates.push(new Date(date1.setDate(date1.getDate() + 1)));
}
alert(alldates.join('\n'));
To echo the other answers, the issue is that the element being pushed to the array isn't a value which stays the same - it refers to a Date object which changes in the loop, so all references to date1 stored in alldates are set to the final value of date1.
The accepted answer does the job, but it also mutates the value of date1. The OP set up the code with this side effect, which suggests that this isn't a problem for their use case. But if you'd prefer to not mutate date1, here's an alternative ES6-flavored, side effect-free approach:
const date1 = new Date("Sep 23, 2013 12:00:00"); // Monday
const date2 = new Date("Sep 26, 2013 12:00:00"); // Thursday
const msPerDay = 1000 * 60 * 60 * 24; // 86400000
const inclusiveDateLength = (date2 - date1) / msPerDay + 1; // 4
const allDates = Array.from(Array(inclusiveDateLength), (_, i) => {
const newDate = new Date(date1);
newDate.setDate(date1.getDate() + i);
return newDate;
});
console.log(allDates.join("\n"));
Explanation: We create an array, fill it new Dates, and increment the day of the month of each of those Dates with Date.prototype.setDate(). A cool feature of Array.from is that it accepts a map function as its second argument. We leverage the index value (i) in the map function to increment the day of the month of each date - note that this also works for wrap-arounds, such as Sep 29 to Oct 02.
When the Temporal API becomes available, it will probably offer a better solution to this problem.

Javascript date parsing bug - fails for dates in June (??)

I have some javascript which parses an ISO-8601 date. For some reason, it is failing for dates in June. But dates in July and May work fine, which doesn't make sense to me. I'm hoping a fresh set of eyes will help, because I can't see what I'm doing wrong here.
Function definition (with bug)
function parseISO8601(timestamp)
{
var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$");
var matches = regex.exec(timestamp);
if(matches != null)
{
var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
if(matches[7] == "-")
offset = -offset;
var date = new Date();
date.setUTCFullYear(parseInt(matches[1], 10));
date.setUTCMonth(parseInt(matches[2], 10) - 1); //UPDATE - this is wrong
date.setUTCDate(parseInt(matches[3], 10));
date.setUTCHours(parseInt(matches[4], 10));
date.setUTCMinutes(parseInt(matches[5], 10) - offset);
date.setUTCSeconds(parseInt(matches[6], 10));
date.setUTCMilliseconds(0);
return date;
}
return null;
}
Test code
alert(parseISO8601('2009-05-09T12:30:00-00:00').toUTCString());
alert(parseISO8601('2009-06-09T12:30:00-00:00').toUTCString());
alert(parseISO8601('2009-07-09T12:30:00-00:00').toUTCString());
Output
Sat, 09 May 2009 12:30:00 GMT
Thu, 09 Jul 2009 12:30:00 GMT
Thu, 09 Jul 2009 12:30:00 GMT
Update
Thanks for the quick answers, the problem was that the Date object was initially today, which happened to be July 31. When the month was set to June, before I changed the day, it was temporarily June 31, which got rolled forward to July 1.
I've since found the following to be a cleaner implementation, as it sets all the date attributes at once:
function parseISO8601(timestamp)
{
var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$");
var matches = regex.exec(timestamp);
if(matches != null)
{
var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
if(matches[7] == "-")
offset = -offset;
return new Date(
Date.UTC(
parseInt(matches[1], 10),
parseInt(matches[2], 10) - 1,
parseInt(matches[3], 10),
parseInt(matches[4], 10),
parseInt(matches[5], 10),
parseInt(matches[6], 10)
) - offset*60*1000
);
}
return null;
}
The problem is that today is July 31.
When you set:
var date = new Date();
Then date.getUTCDate() is 31. When you set date.setUTCMonth(5) (for June), you are setting date to June 31. Because there is no June 31, the JavaScript Date object turns it into July 1. So immediately after setting calling date.setUTCMonth(5) if you alert(date.getUTCMonth()); it will be 6.
This isn't unique to June. Using your function on the 31st of any month for any other month that does not have 31 days will exhibit the same problem. Using your function on the 29th (non-leap years), 30th or 31st of any month for February would also return the wrong result.
Calling setUTC*() in such a way that any rollovers are overwritten by the correct value should fix this:
var date = new Date();
date.setUTCMilliseconds(0);
date.setUTCSeconds(parseInt(matches[6], 10));
date.setUTCMinutes(parseInt(matches[5], 10) - offset);
date.setUTCHours(parseInt(matches[4], 10));
date.setUTCDate(parseInt(matches[3], 10));
date.setUTCMonth(parseInt(matches[2], 10) - 1);
date.setUTCFullYear(parseInt(matches[1], 10));
The date object starts off with the current date.
It's the 31st today so setting 2009-06-09 gives:
var date = new Date(); // Date is 2009-07-31
date.setUTCFullYear(2009); // Date is 2009-07-31
date.setUTCMonth(6 - 1); // Date is 2009-06-31 = 2009-07-01
date.setUTCDate(9); // Date is 2009-07-09
If you set the date to the 1st before you begin, then you should be safe.
It's because today is July 31. Grant explained the problem. Here's what I believe is a simpler solution. Initialize your date on Jan 1.
var date = new Date(2009,0,1,0,0,0);
It's the order in which you are changing the date.
The date starts out as July 31, so the set of the month fails because there is no 31 in June. (Actually it is rolling over to jul-1.)
After setting the full year, add this:
date.setYUTCDate(1);
It makes it the first of the month wherein every month is valid.
Looks like a bug?
C:\Documents and Settings\me>java org.mozilla.javascript.tools.shell.Main
Rhino 1.7 release 2 2009 03 22
js> date = new Date();
Fri Jul 31 2009 15:18:38 GMT-0400 (EDT)
js> date.setUTCMonth(5); date.toUTCString();
Wed, 01 Jul 2009 19:18:38 GMT
js> date.setUTCMonth(5); date.toUTCString();
Mon, 01 Jun 2009 19:18:38 GMT
EDIT: Nevermind I guess. Question already answered by somebody more knowledgable.

Categories