Take the 2-minute tour ×
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

2012q1

and

2011q4

as the respective outputs.

share|improve this question

8 Answers 8

up vote 3 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 ))
share|improve this answer
    
What do you mean by "POSIX date"? It doesn't look like this POSIX date. In fact it looks more like a GNU date. –  jw013 Feb 15 '12 at 1:05
    
@jw013: My bad. GNU it is. Answer corrected. Thanks. –  smokris Feb 15 '12 at 1:51
1  
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

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.

#!/usr/bin/perl

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
else
  last_month_quarter=${1}q$((($2 - 1) / 4 + 1))
fi
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 / 4 + 1))
y2=$(($y1 - ($m1 == 1)))
m2=$((($m1 + 10) % 12 + 1))
q2=$(($m2 / 4 + 1))
echo This Quarter: $(($y1))q$q1
echo Last Month Quarter: $(($y2))q$q2
share|improve this answer

Use my dateutils:

dconv 2012-01-01 -f '%Y%Q'
=>
  2012Q1

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

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

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

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
else
  echo prev ${y}q$(((m-2)/3+1))
fi

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

Your Answer

 
discard

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.