devTokyo90
devTokyo90

Reputation: 15

Why when adding a date to an existing array it overwrites previous element in that array?

Problem

At the end of my code, you will notice that the elements being added to the array datesArr are somehow being copied to the element in front of it. Also not sure why I'm unable to get the expected output

Example:
1) Starting datesArr = [04/30/2022]
2) Adding date 03/30/2022 to datesArr1 overwrites datesArr[0] so then I have an array output that looks like
[04/30/2022, 04/30/2022]

as opposed to
[04/30/2022, 03/30/2022]

See below for console output: enter image description here

Objective

If given a month-end in Date format and a frequency,
return an array which includes the given month-end and the 11 preceding month-ends by frequency.

Code

//Goal: Populate the datesArr with a list of monthend dates for 12 preceding periods(12 elements in array)
/*
Initialize Variables 
datesArray - Holds all dates
initialDate - first month end date that will be placed in the array and every preceding month-end will be calculated based on it
targetDate - Target date is the month end date at the time that will be used to calculate the next preceding month end
frequecy - value that will be used to determine frequency of months (E.g. 1 = 1 month(Monthly), 3 = 3 months(quarterly)). This vaule is used in deltaOfDays function
period - represent the number of month end dates that should be included in the array (E.g. period of 12 is an datesArr of 12 elements)
duration of months - repsents the number of months between month ends(E.g. durationOfMonths = 3 , means quarterly 04/30/2022 to 01/31/2022)
*/

let datesArr = [];
const initialDate = new Date (2022, 03, 30);
let targetDate;
const period = 12;
const durationOfMonths = 1;

//Step1: initialize first element of datesArr with initialDate value and other elements used in for loop

datesArr[0] = initialDate
console.log(datesArr[0])

let numberOfDays; //calculated by deltaOfDays function and represents value of days to be subtracted from targetDate
let newMonthEndDate; // holds the newMonthEndDate value that will be added as the next element in datesArr after being calculated subtracting numberOfDays from targetDate



//Step2: Loop through array period number of times. On each loop identify target element and use it calculate subsequent month end date in the array
for (let i = 0; i < period; i++){
    console.log("Loop iteration #" + i)
    //assign array element to targetDate
    targetDate = datesArr[i];
    console.log("targetDate value is: " + targetDate)

    //calculate the numberOfDays to subtract from the target date such as to arrive at the new monthend date by calling a function deltaOfDays
    numberOfDays = deltaOfDays(targetDate, durationOfMonths)
    console.log("The numberOfDays: " + numberOfDays);

    //subtract the numberOfDays from the targetdate to arrive at newMonthEndDate which is stored as a Date object
    newMonthEndDate = new Date(targetDate.setDate(targetDate.getDate() - numberOfDays));
    console.log("newMonthEnd value: " + newMonthEndDate)
    //assign newMonthEndDate as the next value in the datesArr
    datesArr[i + 1] = newMonthEndDate

    console.log(datesArr)

}


//Function 
function deltaOfDays(targetDate, durationOfMonths){
    //array of number of days per month in reverse (E.g. Jan = daysPerMonth[11])
        const daysPerMonth = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 28, 31]
        //set index to begin array based number value of Month ( E.g. Apr = 3 + 1 = 4th  index - 12 )
        //targetDate = strToDateConvert(targetDate)
        
       let  i = Math.abs(targetDate.getMonth() - 12)
       console.log("deltaDays(): i = " + i)
       const j = i
        //Start at initial month and loop through at durationOfMonths - 1 to account for initialization of element[0] already
        for(i; i <= (i + durationOfMonths); i++ ){
            //add days per month to sum
            
            numberOfDays =+ daysPerMonth[j];

            //remove first element of array(DEC) and add to the end 
            temp = daysPerMonth.shift()
            daysPerMonth.push(temp)

            return numberOfDays
        }
    }

Upvotes: 1

Views: 65

Answers (1)

Jaromanda X
Jaromanda X

Reputation: 1

Firstly: I can't see all the issues in your code, since the code you have is so over complicated for what you want - if you want an answer that uses your code as a starting point, this isn't it :D

This answer takes advantage of the fact that

new Date(2022, 4, 0)

will result in the LAST day of April 2022 - i.e. since month is 0 based, it's like you're saying "give me the 0th day of May 2022" ... which is the day before the 1st May 2022 ... so, 30 April 2022

Knowing that, and the fact that negative numbers are also allowed in month (in fact in any argument) and the constructor will deal with it for you, the solution is really simple

new Date(2022,  4, 0) - April 30 2022
new Date(2022,  3, 0) - March 31 2022
new Date(2022,  2, 0) - February 28 2022
new Date(2022,  1, 0) - January 31 2022
new Date(2022,  0, 0) - December 31 2021
new Date(2022, -1, 0) - November 30 2021
... etc

Now - if you want the array to be actual Date objects, then the code is simply

const makeDates = (startYear, startMonth, duration = 1, length = 12) =>
    Array.from({ length }, (_, index) =>
        new Date(startYear, startMonth - index * duration, 0)
    );
    
console.log(makeDates(2022, 4, 1));
console.log(makeDates(2022, 4, 3));

before rejecting this snippet, take note that the date is in UTC

If you just want strings as per your expected output:

const makeDates = (startYear, startMonth, duration = 1, length = 12) =>
    Array.from({ length }, (_, index) =>
        new Date(startYear, startMonth - index * duration, 0)
            .toLocaleDateString("en-US")
            .split("/")
            .map((v) => v.padStart(2, 0))
            .join("/")
    );
    
console.log(makeDates(2022, 4, 1));
console.log(makeDates(2022, 4, 3));

Upvotes: 1

Related Questions