Generate quarter dates with begin date and end date

Hi All,

I am trying to generate quarter dates with user giving input as begin date and end date. Example: Input by user:

begin_date = "2009-01-01"
end_date = 2010-04-30"

required output:

2009-01-01 2009-03-31 09Q01
2009-04-01 2009-06-30 09Q02
.
.
till
2010-01-01 2010-03-31 10Q01

TIA

Here's one way to do it with Perl:

$
$
$ # display the content of the Perl program
$ cat -n printqtr.pl
     1  #!perl -w
     2  use Date::Calc qw (Add_Delta_YMD Date_to_Days);
     3
     4  # 1st parameter is start date; 2nd is end date
     5  # no input validation done here
     6  @sdate = split(/-/,$ARGV[0]);
     7  @edate = split(/-/,$ARGV[1]);
     8
     9  # determine the beginning quarter for the loop
    10  if ($sdate[1]/3 == int($sdate[1]/3)) {
    11    $add_mon = 3*($sdate[1]/3-1);
    12    $qtr = $sdate[1]/3;
    13  } else {
    14    $add_mon = 3*int($sdate[1]/3);
    15    $qtr = int($sdate[1]/3)+1;
    16  }
    17  @x = Add_Delta_YMD($sdate[0],1,1, 0,$add_mon,0);
    18
    19  # determine the ending quarter for the loop
    20  if ($edate[1]/3 == int($edate[1]/3)) {
    21    $eadd_mon = 3*($edate[1]/3);
    22  } else {
    23    $eadd_mon = 3*(int($edate[1]/3)+1);
    24  }
    25  @y = Add_Delta_YMD($edate[0],1,1, 0,$eadd_mon,-1);
    26
    27  # and now loop from beginning quarter to ending quarter
    28  while (Date_to_Days(@x) < Date_to_Days(@y)) {
    29    printf("%4d-%02d-%02d\t%4d-%02d-%02d\t%sQ%02d\n",
    30           @x, Add_Delta_YMD(@x, 0,3,-1), substr($x[0],2,2), $qtr);
    31    @x = Add_Delta_YMD(@x, 0,3,0);
    32    #  roll over quarter to 1, beyond 4
    33    $qtr++;
    34    $qtr = $qtr > 4 ? 1 : $qtr;
    35  }
$
$ # test it for different cases, boundary conditions etc.
$
$ # both parameters identical
$ perl printqtr.pl 2009-01-01 2009-01-01
2009-01-01      2009-03-31      09Q01
$
$ # dates within a quarter
$ perl printqtr.pl 2009-01-01 2009-01-20
2009-01-01      2009-03-31      09Q01
$
$ # dates spanning multiple quarters of the same year
$ perl printqtr.pl 2009-01-01 2009-04-01
2009-01-01      2009-03-31      09Q01
2009-04-01      2009-06-30      09Q02
$
$ # dates spanning multiple quarters of multiple years
$ perl printqtr.pl 2009-01-01 2011-08-28
2009-01-01      2009-03-31      09Q01
2009-04-01      2009-06-30      09Q02
2009-07-01      2009-09-30      09Q03
2009-10-01      2009-12-31      09Q04
2010-01-01      2010-03-31      10Q01
2010-04-01      2010-06-30      10Q02
2010-07-01      2010-09-30      10Q03
2010-10-01      2010-12-31      10Q04
2011-01-01      2011-03-31      11Q01
2011-04-01      2011-06-30      11Q02
2011-07-01      2011-09-30      11Q03
$
$ # dates in incorrect order
$ perl printqtr.pl 2011-08-01 2001-08-28
$
$

HTH,
tyler_durden

Thanks tyler_durden, it is working... thanks a lot...
can it be done using awk? just wanted to know...:slight_smile:

Hi Tyler,

Suppose if Igive start date as 2000-10-01 and end date as 2010-05-31

Can I get output as

2009-10-01 2009-12-31 09Q04
2010-01-01 2010-03-31 10Q01
2010-04-01 2010-05-31 10Q02

Well, what do you see when you pass those parameters to the program ?

tyler_durden

2009-10-01 2009-12-31 09Q04
2010-01-01 2010-03-31 10Q01
2010-04-01 2010-06-30 10Q02

Instead of 2010-06-30 can I get the end provided as output...

I guess you are passing "2009-10-01" as the first parameter and not "2000-10-01" as mentioned in your earlier post:

Set the value of @y to the lesser of @y and @edate at line no. 26 of the script.

tyler_durden

Hi Tyler,

Yep it is 2009-10-01, typo

I mean suppose if I give the input as sdate as 2009-10-01 and edate as 2010-05-31

I have to get following output:

2009-10-01 2009-12-31 09Q04
2010-01-01 2010-03-31 10Q01
2010-04-01 2010-05-31 10Q02

But from your code, I get the following output:

2009-10-01 2009-12-31 09Q04
2010-01-01 2010-03-31 10Q01
2010-04-01 2010-06-30 10Q02

And if I give input as sdate as 2009-10-01 and edate as 2010-06-30

I have to get following output:

2009-10-01 2009-12-31 09Q04
2010-01-01 2010-03-31 10Q01
2010-04-01 2010-06-30 10Q02

I have tried modying the code as you said, it is giving the fllowing error:

Useless use of numeric lt (<) in void context at qtr_dates.pl line 26.

TIA

What did you try ?

tyler_durden

1 Like
if (($edate[0],$edate[1],$edate[2]) < @y) {
    @y = ($edate[0],$edate[1],$edate[2]);
}
else
{ @y = Add_Delta_YMD($edate[0],1,1, 0,$eadd_mon,-1);
}

I am not sure, if what I am doing is right... correct me if I am wrong here