2

I need a simple help. I wuold like to have a function that generate an array (or a list) of quarters between two dates, in JavaScript. The first one is fixed, while the second date is today.

For example: I wish I have a list of quarters between the first day of 2016 and today. So I would like to have this kind of list

{Gen-Feb-Mar 2016,
Apr-May-June 2016,
Jul-Ago-Sep 2016,
Oct-Nov-Dec 2016,
Gen-Feb-Mar 2017}

The final purpose is to put it into a combo selection.

Could anyone help me?

Thanks in advance

Raul
  • 115
  • 5
  • 16
  • We can help, show us what you have so far. –  Jun 14 '17 at 13:31
  • 1
    might want to take a look at this library: https://momentjs.com/ – c2huc2hu Jun 14 '17 at 13:56
  • You could start by working out the quarter for a particular date, see [*Get current quarter in year with javascript*](https://stackoverflow.com/questions/11981453/get-current-quarter-in-year-with-javascript). What have you tried? – RobG Jun 14 '17 at 20:44
  • Combine @RobG's link with [get array of dates between 2 dates](https://stackoverflow.com/questions/4413590/javascript-get-array-of-dates-between-2-dates) and you have yourself an answer. – Heretic Monkey Jun 14 '17 at 23:00
  • Thanks to all of you that helped me! Ultimately I chose the solution of @Joseph Marikle for the reason that fits more easily to the rest of the logic. – Raul Jun 16 '17 at 10:29

4 Answers4

3

If you're just trying to build the list you have here, you can iterate over the difference of the start year to the current year and then calculate the current quarter with parseInt(new Date().getMonth() / 3 + 1)

var d = new Date(),
  y = d.getFullYear(),
  m = d.getMonth(),
  quarters = ['Jan-Feb-Mar', 'Apr-May-Jun', 'Jul-Aug-Sep', 'Oct-Nov-Dec'],
  options = [];

for (var pastYear = 2016; pastYear < y; pastYear++) {
  quarters.forEach(q => options.push(q + ' ' + pastYear));
}
quarters.slice(0, parseInt(m / 3 + 1)).forEach(q => options.push(q + ' ' + y));

console.log("current date: " + d);
console.log(options);
Joseph Marikle
  • 76,418
  • 17
  • 112
  • 129
  • Thank you. I like your solution. Just one thing, I deleted the +1 from the 'parseInt(m/3 + 1)' because I need only quarters ended ;) – Raul Jun 16 '17 at 10:33
  • @Lorenzo You're welcome. Glad I could help, and good work on finding what was needed to adapt it to your needs. I was a little worried about readability. :P – Joseph Marikle Jun 16 '17 at 14:14
1

Assuming quarters are sections of 3 months, so Jan-Mar is Q1, Apr-Jun is Q2 etc. then you can simply work out the quarter of the start date, then just keep adding 3 months until you get to the quarter of the last date.

Quarters can be represented as yyyyQq, e.g. 15 June 2017 is 2017Q2. Calculating the quarter is then just:

Math.ceil(month/3)

function getQuarter(date) {
  return date.getFullYear() + 'Q' + Math.ceil((date.getMonth()+ 1)/3);
}

function listQuarters(sDate, eDate) {

  // Ensure start is the earlier date;
  if (sDate > eDate) {
    var t = eDate;
    eDate = sDate;
    sDate = t;
  }

  // Copy input start date do don't affect original
  sDate = new Date(sDate);
  
  // Set to 2nd of month so adding months doesn't roll over
  // and not affected by daylight saving
  sDate.setDate(2);

  // Initialise result array with start quarter
  var startQ = getQuarter(sDate);
  var endQ   = getQuarter(eDate);
  var result = [startQ];
  
  // List quarters from start to end
  while (startQ != endQ) {
    sDate.setMonth(sDate.getMonth() + 3);
    startQ = getQuarter(sDate);
    result.push(startQ);
  } 
  
  return result;
}

var start = new Date(2016,0,31);  // 31 Jan 2016
var end   = new Date();           // Today

console.log('Current quater: ' + getQuarter(end));
console.log('Quarter list  : ' + listQuarters(start, end));
RobG
  • 142,382
  • 31
  • 172
  • 209
0

Create a start date and an end date, in a loop increase start date until it equals end date, count quarterchanges:

//A quarter is defined as a fourth of a year
function getQuarter(date) {
  return Math.floor(date.getMonth() / 3);
}
//A quartertimestamp adds the product quarters of the current year to the quartercount
function getQuarterTimestamp(date) {
  return getQuarter(date) + ":" + date.getFullYear();
}
//quartersTillNow calculates how many quarters in the past a date is
function quartersTillNow(origialFrom) {
  //From is a clone of origialFrom
  var from = new Date(origialFrom.getTime());
  //To is today
  var to = new Date();
  //Variable to count number of quarters between
  var quarters = 0;
  //While from is in the past, add month to from
  while (getQuarterTimestamp(from) != getQuarterTimestamp(to)) {
    //newFrom is defined as a clone of from
    var newFrom = new Date(from.getTime());
    //Add a month
    newFrom.setMonth(newFrom.getMonth() + 1);
    //If quarter has changed
    if (getQuarter(newFrom) != getQuarter(from)) {
      //Add a quarter
      quarters++;
    }
    //overwrite from and keep repeat
    from = newFrom;
  }
  //return count of quarters
  return quarters;
}
//TEST
var from = new Date();
from.setFullYear(2000);
console.log(from, "was", quartersTillNow(from), "quarters ago");
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • Seems to me that for a date 17 years ago, there should have been about 17x4 quarters, or 68 quarters. This answer gives 51. Where did the other 4 years go? I don't understand the logic behind `getQuarter(date) + date.getFullYear() * 4`. – RobG Jun 14 '17 at 20:48
  • @RobG You are correct. In the `getQuarter` i should divide by months in a quarter (`3`) not number of quarters (`4`). It is fixed now. `getQuarterTimestamp` meant to get a unique id for each quarter ever. Since there are `4` quarters in a year it should be (`currentQuarter` + `4 times the current year`). I have made another way of generating the ID that hopefully makes more sense to you. – Emil S. Jørgensen Jun 15 '17 at 06:50
0

Here's a solution that doesn't loop through every date, just procedurally adding quarters up to, but not including, the current quarter.

function listQuarters(sDate, eDate) {

    //Get the quarter of the current month
    var sQuarter = Math.floor((sDate.getMonth()-1)/3)+1;
    var eQuarter = Math.floor((eDate.getMonth()-1)/3)+1;

    var sYear = sDate.getYear();
    var eYear = eDate.getYear();

    var quarterNames = ['Jan-Feb-Mar', 'Apr-May-Jun', 'Jul-Aug-Sep', 'Oct-Nov-Dec'];
    var quarterList = [];

    while(sQuarter != eQuarter && sYear != eYear) {

        quarterList.push(sYear + ' Q' + quarterNames[sQuarter-1]);

        sQuarter++;

        if(sQuarter > 4) {
            sQuarter = 1;
            sYear++;
        }
    }

    return quarterList;

}