Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS time - make an array for each year between two dates

I have two variables: Start & End and basically I need to create an array for each complete year between these two dates.

I will need to record the total withdrawals taken in each year in the array but not sure how to start creating the array for each policy year.

Any help would be appreciated.

like image 691
Webezine Avatar asked Aug 25 '26 07:08

Webezine


2 Answers

For simple scenarios (where using a library would be overkill) , I would use this:

const rangeOfYears = (start, end) => Array(end - start + 1)
  .fill(start)
  .map((year, index) => year + index)

If your input is not an integer but a Date object, use .getFullYear()


So for instance, if we wanted the years between 2014 and 2020 (inclusive), this would be:

// Using integers for years
rangeOfYears(2014, 2020)

// Using `Date` objects for years
rangeOfYears(new Date("Jun 26 2014").getFullYear(), new Date().getFullYear())

// For both the result would be:
// [2014, 2015, 2016, 2017, 2018, 2019, 2020]

Although the title does not state this, the question author mentions "each complete year between these two dates". An exact definition of what constitues a "complete" year is not mentioned, but that could either be:

  1. Years that have a full 12 months
    In this case, the first and last item should always be removed:

    .slice(1, -1)
    // Which gives: [2015, 2016, 2017, 2018, 2019]
    
    
  2. Each 12 months from the start date onwards
    In this case, a filter would be needed to see if the last year falls within range:
    (This would require Date objects to work with)

    .filter((year, index) => 
        // 31536000000 = 60 * 60 * 24 * 365 * 1000 = one year in milliseconds
        index < (end.getTime() - start.getTime()) / 31536000000)
        // Which gives: [2014, 2015, 2016, 2017, 2018, 2019]
    
    

Code examples

Putting all of this together gives us:

Without "complete year" filter

/* Example without "complete year" filter */
const rangeOfYears = (start, end) => Array(end - start + 1)
  .fill(start)
  .map((year, index) => year + index)

let a = rangeOfYears(2014, 2020)
let b = rangeOfYears(new Date("Jun 26 2014").getFullYear(), new Date().getFullYear())

console.log(a)
console.log(b)

With "complete year = 12 full months" filter

/* Example with "complete year = 12 full months" filter */
const rangeOfYears = (start, end) => Array(end - start + 1)
  .fill(start)
  .map((year, index) => year + index)
  .slice(1, -1)

let c = rangeOfYears(2014, 2020)
let d = rangeOfYears(new Date("Jun 26 2014").getFullYear(), new Date().getFullYear())

console.log(c)
console.log(d)

With "complete year = each 12 months" filter

/* Example with "complete year = each 12 months" filter */
const rangeOfFullYears = (start, end) => {
  
  // Lets not do this inside the "filter"...
  const fullYears = (end.getTime() - start.getTime()) / 31536000000
  
  return Array(end.getFullYear() - start.getFullYear() + 1)
    .fill(start.getFullYear())
    .map((year, index) => year + index)
    .filter((year, index) => index < fullYears)
}

let e = rangeOfFullYears(new Date("Jun 26 2014"), new Date())

console.log(e)
like image 188
Potherca Avatar answered Aug 27 '26 19:08

Potherca


If you do a lot of date manipulations, I'd recommend using Moment.js. With the Moment.js diff function, Moment.js will do an exact calculation on differences and not just subtract the year component on the Date object.

Example spanning 2 years:

var Start = new Date("June 26, 2012 11:13:00");
var End = new Date("January 1, 2015 11:13:00");
var years = moment(End).diff(Start, 'years');
var yearsBetween = [];
for(var year = 0; year < years; year++)
    yearsBetween.push(Start.getFullYear() + year);

Returns:

yearsBetween
[2012, 2013]

Example spanning 3 years:

var Start = new Date("June 26, 2012 11:13:00");
var End = new Date("June 26, 2015 11:13:00");
var years = moment(End).diff(Start, 'years');
var yearsBetween = [];
for(var year = 0; year < years; year++)
    yearsBetween.push(Start.getFullYear() + year);

Returns:

yearsBetween
[2012, 2013, 2014]

The first example only spans 2 years because it does not have 3 full years, even though the year on End is 3 years later than the year on Start. Anything beyond the same month/day of the start date in a later year counts as a full year. This is why the second example spans a full 3 years.

EDIT: Example of how to do a diff without moment.js:

const msPerYear = 1000 * 60 * 60 * 24 * 365;

function diffYear(d1, d2) {
  const utc1 = Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate());
  const utc2 = Date.UTC(d2.getFullYear(), d2.getMonth(), d2.getDate());
  return Math.floor((utc2 - utc1) / msPerYear);
}

Spanning 7 years:

var Start = new Date("June 26, 2012 11:13:00");
var End = new Date("January 1, 2020 11:13:00");

var diff = diffYear(Start, End);

Returns:

7

Spanning 8 years:

var Start = new Date("June 26, 2012 11:13:00");
var End = new Date("June 26, 2020 11:13:00");

var diff = diffYear(Start, End);

Returns:

8

Note: It gets complicated when calculating the diff with leap years as they change the milliseconds per year for just the years which are leap years.

like image 22
Cameron Tinker Avatar answered Aug 27 '26 20:08

Cameron Tinker