1

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 =
  • Do you need to run date on the Solaris host? – Jeff Schaller May 5 '17 at 12:39
  • assume so, as I don't know what other alternative would be available to get the current date? – Ben Hamilton May 5 '17 at 12:40
  • Theoretically you could generate the dates somewhere else, like a gnu Linux box (which has more features) then transfer the dates or a resulting sql script to the Solaris box. – Jeff Schaller May 5 '17 at 12:41
  • 1
    You can use the date command to get the current month. Then you have one of 4 choices of which quarter it is. From there you have 4 cases to calculate the years and days. You can can hard code days and months and need to retrieve year an maybe subtract one if in first quarter and you need previous quarter. – Robert Jacobs May 5 '17 at 12:52
  • 1
    @JeffSchaller thank you, shellcheck.net looks awesome! :) – Ben Hamilton May 5 '17 at 15:21
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 =.

| improve this answer | |
  • 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 unix.stackexchange.com/questions/199900/… helped. – Ben Hamilton May 9 '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 9 '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 9 '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 9 '17 at 10:49
  • Thanks, I didn't know how powerful printf was, I found this with explains more. blog.fpmurphy.com/2008/10/… – Ben Hamilton May 9 '17 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.