Here's my attempt in Perl, in case Perl is an option for you.
The following program accepts a date in "yyyymmdd" format and returns the start/end date pairs for the previous quarters and month as per your post.
If no date is passed, it uses today's date.
Only the core modules are used, so no additional module from CPAN is required.
However, these core modules - Time::Piece and Time::Seconds are available from Perl version 5.8 onwards, so that's the minimum version required.
$
$ cat -n get_quarter_dates.pl
1 #!/usr/bin/perl -w
2 # ====================================================================
3 # Usage: perl get_quarter_dates.pl 20170705
4 # perl get_quarter_dates.pl
5 # Desc : If a date is passed in "YYYYMMDD" format, then it is used.
6 # Otherwise, current date is used.
7 # ====================================================================
8 use strict;
9 use Time::Piece;
10 use Time::Seconds;
11
12 my $date;
13 my $start_fiscal_yr;
14 # Fiscal year starts from July. If that changes, change the next line.
15 my $start_fiscal_month = "07";
16
17 # Use either the date passed or today's date as the working date.
18 if ($#ARGV >= 0) {
19 $date = Time::Piece->strptime($ARGV[0], "%Y%m%d");
20 } else {
21 $date = Time::Piece->new;
22 }
23
24 # Determine the start of fiscal year
25 if ($date->mon > $start_fiscal_month) {
26 # Go to the fiscal month of current year
27 $start_fiscal_yr = Time::Piece->strptime($date->year.$start_fiscal_month."01", "%Y%m%d");
28 } else {
29 # Go back 12 months to the previous year.
30 # Then set the fiscal month of previous year as start of fiscal year.
31 my $prev_yr_dt = $date->add_months(-12);
32 $start_fiscal_yr = Time::Piece->strptime($prev_yr_dt->year.$start_fiscal_month."01", "%Y%m%d");
33 }
34
35 # Set up the quarter start/end dates and then loop through the quarters.
36 my $qtr_start_date = $start_fiscal_yr;
37 my $qtr_end_date = $start_fiscal_yr->add_months(3) - ONE_DAY;
38 foreach my $i (1..4) {
39 # If quarter end is later than working date then determine previous month end
40 # and print the interval (qtr_start, prev_mth_end) only if qtr_start is earlier
41 # than previous month end.
42 if ($qtr_end_date >= $date) {
43 my $curr_mth_start_date = Time::Piece->strptime($date->strftime("%Y-%m-01"), "%Y-%m-%d");
44 my $prev_mth_end_date = $curr_mth_start_date - ONE_DAY;
45 if ($qtr_start_date < $prev_mth_end_date){
46 printf("%s %s\n", $qtr_start_date->ymd, $prev_mth_end_date->ymd);
47 }
48 last;
49 }
50 printf("%s %s\n", $qtr_start_date->ymd, $qtr_end_date->ymd);
51 # Move on to the next quarter.
52 $qtr_start_date = $qtr_end_date + ONE_DAY;
53 $qtr_end_date = $qtr_start_date->add_months(3) - ONE_DAY;
54 }
55
$
$
A few test runs:
$
$ # No date passed; uses today's date.
$ perl get_quarter_dates.pl
2017-07-01 2017-07-31
$
$ # For July 2017, generate the start/end dates of 4 quarters of previous fiscal year
$ perl get_quarter_dates.pl 20170705
2016-07-01 2016-09-30
2016-10-01 2016-12-31
2017-01-01 2017-03-31
2017-04-01 2017-06-30
$
$ perl get_quarter_dates.pl 20170805
2017-07-01 2017-07-31
$
$ perl get_quarter_dates.pl 20170905
2017-07-01 2017-08-31
$
$ perl get_quarter_dates.pl 20171005
2017-07-01 2017-09-30
$
$ perl get_quarter_dates.pl 20171105
2017-07-01 2017-09-30
2017-10-01 2017-10-31
$
$ perl get_quarter_dates.pl 20171205
2017-07-01 2017-09-30
2017-10-01 2017-11-30
$
$ perl get_quarter_dates.pl 20180105
2017-07-01 2017-09-30
2017-10-01 2017-12-31
$
$ perl get_quarter_dates.pl 20180205
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-01-31
$
$ perl get_quarter_dates.pl 20180305
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-02-28
$
$ perl get_quarter_dates.pl 20180405
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-03-31
$
$ perl get_quarter_dates.pl 20180505
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-03-31
2018-04-01 2018-04-30
$
$ perl get_quarter_dates.pl 20180605
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-03-31
2018-04-01 2018-05-31
$
$ # And back to the same logic for July of next year
$ perl get_quarter_dates.pl 20180705
2017-07-01 2017-09-30
2017-10-01 2017-12-31
2018-01-01 2018-03-31
2018-04-01 2018-06-30
$
$
The start of the fiscal month is set as "07" (July) at line # 15, but it can be changed.
I changed the start of fiscal month to "10" (October) below:
$
$ cat -n get_quarter_dates.pl | sed -n 1,16p
1 #!/usr/bin/perl -w
2 # ====================================================================
3 # Usage: perl get_quarter_dates.pl 20170705
4 # perl get_quarter_dates.pl
5 # Desc : If a date is passed in "YYYYMMDD" format, then it is used.
6 # Otherwise, current date is used.
7 # ====================================================================
8 use strict;
9 use Time::Piece;
10 use Time::Seconds;
11
12 my $date;
13 my $start_fiscal_yr;
14 # Fiscal year starts from July. If that changes, change the next line.
15 my $start_fiscal_month = "10";
16
$
$
And the script works accordingly:
$
$ perl get_quarter_dates.pl 20171005
2016-10-01 2016-12-31
2017-01-01 2017-03-31
2017-04-01 2017-06-30
2017-07-01 2017-09-30
$
$ perl get_quarter_dates.pl 20171105
2017-10-01 2017-10-31
$
$ perl get_quarter_dates.pl 20171205
2017-10-01 2017-11-30
$
$ perl get_quarter_dates.pl 20180105
2017-10-01 2017-12-31
$
$ perl get_quarter_dates.pl 20180205
2017-10-01 2017-12-31
2018-01-01 2018-01-31
$
$ perl get_quarter_dates.pl 20180905
2017-10-01 2017-12-31
2018-01-01 2018-03-31
2018-04-01 2018-06-30
2018-07-01 2018-08-31
$
$
Thereafter, incorporating this script in a shell script should be easy.
I assume you are connecting to PostgreSQL via the "psql" command-line utility.
If so, the Bash shell script looks like this:
$
$ cat -n fetch_pg_data.sh
1 #!/bin/bash
2 # ========================================================================================
3 # If a date in "YYYYMMDD" format is passed to this shell script, it will be fed to
4 # the Perl program "get_quarter_dates.pl". The output from the Perl program is
5 # passed to the PostgreSQL client "psql". The output file is named uniquely according
6 # to the start and end dates.
7 # ========================================================================================
8 perl get_quarter_dates.pl $1 |
9 while read dt_start dt_end
10 do
11 outfile="data_${dt_start}_${dt_end}.log"
12 echo "Start Date : $dt_start"
13 echo "End Date : $dt_end"
14 echo "Spool file : $outfile"
15 echo "================================="
16 psql -d mydb -o $outfile -c "select sum(values) from t_data where dt between '$dt_start' and '$dt_end'"
17 done
18
$
$
If the script has to be run for some previous date, it can be passed to the shell script.
The shell script, in turn, passes it on to Perl.
The "outfile" name is based on the start/end dates.
Execution of the shell script:
$
$ . fetch_pg_data.sh 20170705
Start Date : 2016-07-01
End Date : 2016-09-30
Spool file : data_2016-07-01_2016-09-30.log
=================================
Start Date : 2016-10-01
End Date : 2016-12-31
Spool file : data_2016-10-01_2016-12-31.log
=================================
Start Date : 2017-01-01
End Date : 2017-03-31
Spool file : data_2017-01-01_2017-03-31.log
=================================
Start Date : 2017-04-01
End Date : 2017-06-30
Spool file : data_2017-04-01_2017-06-30.log
=================================
$
$
$ cat data_2016-07-01_2016-09-30.log
sum
------------------
50.4268608423881
(1 row)
$
$ cat data_2016-10-01_2016-12-31.log
sum
------------------
51.2326508448459
(1 row)
$
$ cat data_2017-01-01_2017-03-31.log
sum
------------------
47.1403563958593
(1 row)
$
$ cat data_2017-04-01_2017-06-30.log
sum
------------------
44.4815620388836
(1 row)
$
$