2

I am writing a shell script, and need to calculate the first and last days of a quarter from the current date. This is for use in Ingres 10 SQL statements triggered from within the script. The Ingres runs on a Solaris server with ksh.

So, if today is 31/01/17, I would want to calculate the following

  1. the first date of the current quarter (01/01/17)
  2. the last date of the current quarter (31/03/17). It would be OK here to return an exclusive to date if necessary (i.e. 01/04/17)
  3. the first date of the previous quarter (01/10/16)
  4. the last date of the previous quarter (31/12/16). An exclusive-to result of 01/01/17 would also be OK.

Can anyone please help? I've seen questions related to getting the quarter number but that's not really helping.

I've tried the following but its not working as the variables are not being populated in the case statement

CURR_MONTH=`date +%m`
echo "Current month num = $CURR_MONTH"

CURR_YEAR=`date +%Y`
echo "Current year = $CURR_YEAR"

let "LAST_YEAR = $CURR_YEAR - 1"
echo "Last year = $LAST_YEAR"


case $CURR_MONTH in
05) CURR_Q_FROM = 01.04.${CURR_YEAR}
CURR_Q_TO = "30.06.${CURR_YEAR}"
PREV_Q_FROM = "01.01.${CURR_YEAR}"
PREV_Q_TO = "31.03.${CURR_YEAR}" ;;
esac

echo "Current Q From = $CURR_Q_FROM"
echo "Current Q To = $CURR_Q_TO"
echo "Prev Q From = $PREV_Q_FROM"
echo "Prev Q To = $PREV_Q_TO"

I get the following output

Current month num = 05
Current year = 2017
Last year = 2016
Month to be extracted = April 2017
./stats_report_monthly.sh[85]: CURR_Q_FROM:  not found
./stats_report_monthly.sh[86]: CURR_Q_TO:  not found
./stats_report_monthly.sh[87]: PREV_Q_FROM:  not found
./stats_report_monthly.sh[88]: PREV_Q_TO:  not found
Current Q From =
Current Q To =
Prev Q From =
Prev Q To =
Ben Hamilton
  • 143
  • 7

1 Answers1

2

With ksh93 (also /bin/sh on Solaris 11):

#! /usr/bin/ksh -
eval "$(printf '%(y=%Y m=%-m)T')"
first=$(printf '%(%F)T' "$y-$(((m-1)/3*3+1))-1")
last=$(printf '%(%F)T' "$first next 2 months last day")
echo "$first $last"

first2=$(printf '%(%F)T' "$first last 3 months")
last2=$(printf '%(%F)T' "$first2 next 2 months last day")
echo "$first2 $last2"

Example:

$ ./quarter
2017-04-01 2017-06-30
2017-01-01 2017-03-31
$ faketime 2017-01-31 ./quarter
2017-01-01 2017-03-31
2016-10-01 2016-12-31

Using your approach, that would be:

eval "$(date +'y=%Y m=%m')"
case $m in
  (0[1-3])
     echo "$y-01-01 $y-03-31"
     echo "$((y-1))-10-01 $((y-1))-12-31";;
  (0[4-6])
     echo "$y-04-01 $y-06-30"
     echo "$y-01-01 $y-03-31";;
  (0[7-9])
     echo "$y-07-01 $y-09-30"
     echo "$y-04-01 $y-06-30";;
  (*)
     echo "$y-10-01 $y-12-31"
     echo "$y-07-01 $y-09-30"
esac

In any case, note that the syntax of variable assignments in Bourne-like shells is:

var=value

No space on either side of =.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • I tried first section and got './test.sh[3]: (m-1)/3*3+1: bad number' error. I tried to find out which version of ksh I have and none of the three solutions in the Q in this post https://unix.stackexchange.com/questions/199900/how-can-i-safely-get-the-version-of-ksh helped. – Ben Hamilton May 09 '17 at 10:27
  • @Ben, is it Solaris 11 or older? On Solaris 11, `/bin/sh`, `/bin/ksh` and `/bin/ksh93` are `ksh93u` while `/usr/xpg4/bin/sh` is based on ksh88i (Bourne shell in `/usr/sunos/bin/sh`). You'll have no luck with Solaris 10 and older where `/bin/sh` is a Bourne shell (!), `/bin/ksh` and `/usr/xpg4/bin/sh` are based on ksh88i, `/usr/dt/bin/dtksh` (if installed) based on ksh93d (from over 20 years ago!) – Stéphane Chazelas May 09 '17 at 10:41
  • It's Solaris 10. We are getting new M10 servers soon which I'm hoping will have Solaris 11 on, I'll check. – Ben Hamilton May 09 '17 at 10:48
  • @Ben, Then you can use the second approach which should work with any POSIX shell (`/usr/xpg4/bin/sh` or `/bin/ksh` in Solaris 10). – Stéphane Chazelas May 09 '17 at 10:49
  • Thanks, I didn't know how powerful printf was, I found this with explains more. http://blog.fpmurphy.com/2008/10/ksh93-date-manipulation.html#sthash.n0mppK9t.dpbs – Ben Hamilton May 09 '17 at 11:01
  • I now require the first and last date of the previous month, I don't think I'm going to be able to get this without ksh93/printf? – Ben Hamilton May 09 '17 at 11:03
  • @Ben, or use `perl`. A similar question has just been posted today: [How the get last day of previous month in UNIX (HPUX)](//unix.stackexchange.com/a/363866) – Stéphane Chazelas May 09 '17 at 11:04
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/58457/discussion-between-ben-hamilton-and-stephane-chazelas). – Ben Hamilton May 09 '17 at 14:00