Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I'm interested in outputting a representation of the current year-quarter, as well as the year-quarter for the previous month.

If today is 2012 January 1st, I'd like to get




as the respective outputs.

share|improve this question

9 Answers 9

up vote 5 down vote accepted

One (kinda ugly) solution, using BASH arithmetic evaluation and the GNU date command:

echo $(date +%Y)q$(( ($(date +%-m)-1)/3+1 ))
echo $(date -d "-1 month" +%Y)q$(( ($(date -d "-1 month" +%-m)-1)/3+1 ))

Note that the %-m prevents date from 0-padding, so this will still work for August and September.

share|improve this answer
Take $(...) instead of the deprecated backticks. They can easily be nested. – user unknown Feb 15 '12 at 4:45
just be curious: why other answers use 4 as divisor. – LiuYan 刘研 Jan 29 '13 at 10:32
@LiuYan刘研: Not sure. There are 3 months in a quarter, so I think 3 is the correct divisor. (Though that confused me at first, too.) – smokris Jan 29 '13 at 15:10
In September %m gives 09 which bash tries to interpret as octal due to the leading 0, so this throws an error that says 09: value too great for base (error token is "09"). This can be fixed by disabling 0-padding by changing %m to %-m. – Matthew Jul 17 at 22:07

Probably, there is no direct solution.

You could use awk to avoid so many back-ticks.

date +"%Y %m" | awk '{q=int($2/4)+1; printf("%sq%s\n", $1, q);}'
date +"%Y %m" | awk '{q=int($2/4);y=$1;if (q==0){q=4;y=y-1;}; printf("%sq%s\n", y, q);}'

A perl solution would be cleaner but perl and DateTime are an heavy prerequisite.


use DateTime;

my $today = DateTime->now;
print "today: " . $today->year . "q" . $today->quarter . "\n";

my $ago = DateTime->now->subtract( months=> 4);
print "some time ago: " . $ago->year . "q" . $ago->quarter . "\n"
share|improve this answer
Cool. I like the first date/awk line, since it avoids calling (and passing parameters to) date twice. – smokris Feb 15 '12 at 1:49

Split the format with date, calculate with awk, format with printf:

date +"%Y %m" | awk '{printf ("%4dq%1d\n", $1, ($2/4)+1)}'

Just date and bash:

echo $(date +%Yq)$(($(date +%m)/4+1))
share|improve this answer
The first line outputs 2012q0 which is incorrect. – smokris Feb 15 '12 at 4:25
@smokris: You're right - I picked the wrong line of my tests. – user unknown Feb 15 '12 at 4:41

Call date to retrieve the current year and month, and do the rest with arithmetic in the shell.

set $(date '+%Y %m');
this_quarter=${1}q$(($2 / 4 + 1))
if [ $2 -eq 1 ]; then
  last_month_quarter=$(($1 - 1))q4
  last_month_quarter=${1}q$((($2 - 1) / 4 + 1))
share|improve this answer

An alternative, more as a curiosity. If GNU awk is involved, date is not needed:

awk 'BEGIN{print strftime("%Y")"q"int((strftime("%-m")-1)/3)+1}'
share|improve this answer

Basic math for this quarter and last month's quarter:

y1=$(date +%Y)
m1=$(date +%m)
q1=$(( (m1 - 1) / 3 + 1))
y2=$(( y1 - (m1 == 1) ))
m2=$(( (m1 + 10) % 12 + 1 ))
q2=$(( (m2 - 1) / 3 + 1 ))
echo This Quarter: $((y1))q$q1
echo Last Month Quarter: $((y2))q$q2

The script uses the following parts:

  1. $(unix-cmd) - evaluates a command in shell script
  2. $((expr)) - evaluates a mathematical expression
  3. remapping 1..12 -> 1..4 uses the following math (m-1)/3+1
  4. evaluating the previous month uses modulo math
share|improve this answer

Use my dateutils:

dconv 2012-01-01 -f '%Y%Q'

The %q and %Q flags are specific to dateutils, and return the quarter as number or in the form Q<NUMBER>.

share|improve this answer
Very cool. Thanks for the link. – smokris Apr 14 '12 at 1:24
dconv now -f%Y%Q | tr Q q if you really need that Q to be lower cased. (PS: we're packaging this in Fedora with date as the prefix instead of d, so "dateconv".) – mattdm May 28 at 1:36

All solutions that divide by four fail, for instance November:

% echo $(( 11/4+1 ))

The correct math would be:

$(( (m-1)/3 +1 ))

And as such, the quarter of current and previous month would be:

echo curr ${y}q$(((m-1)/3+1))
if [ $m = 1 ]; then
  echo prev $((y-1))q4
  echo prev ${y}q$(((m-2)/3+1))

It's only twelve values to check, really…

% for m in {1..12}; do echo $m Q$(((m-1)/3+1)); done
1 Q1
2 Q1
3 Q1
4 Q2
5 Q2
6 Q2
7 Q3
8 Q3
9 Q3
10 Q4
11 Q4
12 Q4
share|improve this answer
+1 For "All solutions that divide by for fail". You're right! A quarter last for 3 months so the answers should be dividing by 3. – Stephen Quan May 28 at 0:31

Year-Quarter for this month

date +"%Yq$(expr $(expr $(date +%m) - 1) / 3 + 1)"

Year-Quarter for yester-month

date +"%Yq$(expr $(expr $(date -d '-1 month' +%m) - 1) / 3 + 1)"
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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