1

I have a function in Javascript that returns the date ranges of the current/previous/next quarter. For example, for current quarter it would return 2019-01-01 and 2019-03-31. For some reason, a few colleagues have said that the date ranges are inaccurate for them: for them it returns 2018-12-31 and 2019-02-27. I noticed that both of these users are in Germany/Poland region.

Here is my jsFiddle

function formatDate(date) {
    var d = new Date(date),
        month = '' + (d.getUTCMonth() + 1),
        day = '' + d.getUTCDate(),
        year = d.getUTCFullYear();

    if (month.length < 2) month = '0' + month;
    if (day.length < 2) day = '0' + day;

    return [year, month, day].join('-');
}

function getDate_FQ(range){
    var now = new Date();
    switch(range){
        case 'Previous FQ':
            now.setMonth(now.getMonth()-3);
            break;
        case 'Next FQ':
            now.setMonth(now.getMonth()+3);
            break;
        case 'Current FQ':
            break;
    }
    var quarter = Math.floor((now.getUTCMonth() / 3));
    var firstDate = new Date(now.getUTCFullYear(), quarter * 3, 1);
    var endDate = new Date(firstDate.getUTCFullYear(), firstDate.getUTCMonth() + 3, 0);
    return([firstDate, endDate])
}

let [first, end] = getDate_FQ('Current FQ')
console.log(formatDate(first), formatDate(end))

How is it that one date is off by 1 day and the other is off by 1 month and 1 day?

Bijan
  • 7,737
  • 18
  • 89
  • 149
  • The problem is that you are mixing local and UTC methods. Just use one or the other exclusively.. – RobG Mar 25 '19 at 21:09
  • 1
    `formatDate` can be simplified to `new Date(date).toISOString().split('T')[0]` if I'm not mistaken. – 3limin4t0r Mar 25 '19 at 21:10
  • Possible duplicate of [Is the Javascript date object always one day off?](https://stackoverflow.com/questions/7556591/is-the-javascript-date-object-always-one-day-off) – Heretic Monkey Mar 25 '19 at 21:39

2 Answers2

1

If you want to have Date refers to the same time in every timezone, work in UTC and change your code in two lines to:

var firstDate = new Date(Date.UTC(now.getUTCFullYear(), quarter * 3, 1));
var endDate = new Date(Date.UTC(firstDate.getUTCFullYear(), firstDate.getUTCMonth() + 3, 0));
NaDeR Star
  • 647
  • 1
  • 6
  • 13
0

NaDeR Star posted a solution that solved my problem with the timezone but I found a method that was nearly twice as fast when running this 100K times.

Since the dates of the quarter ranges are always the same (Jan1 - Mar31, Apr1 - Jun30, etc) and the only thing changing is the year, it is faster to just combine the year with the date range.

Here is my new solution:

function getDate_FQ(range){
    var now = new Date();
    var dateArr = {0: ['-01-01', '-03-31'], 1: ['-04-01', '-06-30'], 2: ['-07-01', '-09-30'], 3: ['-10-01', '-12-31']}
    switch(range){
        case 'Previous FQ':
            now.setUTCMonth(now.getUTCMonth()-3);
            break;
        case 'Next FQ':
            now.setUTCMonth(now.getUTCMonth()+3);
            break;
        case 'Current FQ':
            break;
    }
    var quarter = Math.floor((now.getUTCMonth() / 3));
    var dates = dateArr[quarter]
    var firstDate = (now.getUTCFullYear()) + dates[0];
    var endDate = (now.getUTCFullYear()) + dates[1];
    return([firstDate, endDate])
}
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
Bijan
  • 7,737
  • 18
  • 89
  • 149
  • You are mixing local and UTC dates and will still get incorrect results for some dates at the very end or start of a quarter due to local timezone differences. E.g. for some one in UTC +10 and at 23:00 on 31 Dec 2018 this function returns the previous quarter as 2018-10-10 to 2018-12-31, which is incorrect. – RobG Mar 25 '19 at 21:17
  • That depends what you want. If you're working with UTC time, you'll get the UTC quarter. Not your local quarter. – 3limin4t0r Mar 25 '19 at 21:32