Sure I could write this myself, but before I go reinventing the wheel is there a function that already does this?
Here is a verbose, but also readable solution that will work for datetime and date instances
def get_quarter(date):
for months, quarter in [
([1, 2, 3], 1),
([4, 5, 6], 2),
([7, 8, 9], 3),
([10, 11, 12], 4)
]:
if date.month in months:
return quarter
if m
is the month number...
import math
math.ceil(float(m) / 3)
For anyone trying to get the quarter of the fiscal year, which may differ from the calendar year, I wrote a Python module to do just this.
Installation is simple. Just run:
$ pip install fiscalyear
There are no dependencies, and fiscalyear
should work for both Python 2 and 3.
It's basically a wrapper around the built-in datetime module, so any datetime
commands you are already familiar with will work. Here's a demo:
>>> from fiscalyear import *
>>> a = FiscalDate.today()
>>> a
FiscalDate(2017, 5, 6)
>>> a.fiscal_year
2017
>>> a.quarter
3
>>> b = FiscalYear(2017)
>>> b.start
FiscalDateTime(2016, 10, 1, 0, 0)
>>> b.end
FiscalDateTime(2017, 9, 30, 23, 59, 59)
>>> b.q3
FiscalQuarter(2017, 3)
>>> b.q3.start
FiscalDateTime(2017, 4, 1, 0, 0)
>>> b.q3.end
FiscalDateTime(2017, 6, 30, 23, 59, 59)
fiscalyear
is hosted on GitHub and PyPI. Documentation can be found at Read the Docs. If you're looking for any features that it doesn't currently have, let me know!
Given an instance x
of datetime.date, (x.month-1)//3
will give you the quarter (0 for first quarter, 1 for second quarter, etc -- add 1 if you need to count from 1 instead;-).
Originally two answers, multiply upvoted and even originally accepted (both currently deleted), were buggy -- not doing the -1
before the division, and dividing by 4 instead of 3. Since .month
goes 1 to 12, it's easy to check for yourself what formula is right:
for m in range(1, 13):
print m//4 + 1,
print
gives 1 1 1 2 2 2 2 3 3 3 3 4
-- two four-month quarters and a single-month one (eep).
for m in range(1, 13):
print (m-1)//3 + 1,
print
gives 1 1 1 2 2 2 3 3 3 4 4 4
-- now doesn't this look vastly preferable to you?-)
This proves that the question is well warranted, I think;-).
I don't think the datetime module should necessarily have every possible useful calendric function, but I do know I maintain a (well-tested;-) datetools
module for the use of my (and others') projects at work, which has many little functions to perform all of these calendric computations -- some are complex, some simple, but there's no reason to do the work over and over (even simple work) or risk bugs in such computations;-).
This is an old question but still worthy of discussion.
Here is my solution, using the excellent dateutil module.
from dateutil import rrule,relativedelta
year = this_date.year
quarters = rrule.rrule(rrule.MONTHLY,
bymonth=(1,4,7,10),
bysetpos=-1,
dtstart=datetime.datetime(year,1,1),
count=8)
first_day = quarters.before(this_date)
last_day = (quarters.after(this_date)
-relativedelta.relativedelta(days=1)
So first_day
is the first day of the quarter, and last_day
is the last day of the quarter (calculated by finding the first day of the next quarter, minus one day).
Here is an example of a function that gets a datetime.datetime object and returns a unique string for each quarter:
from datetime import datetime, timedelta
def get_quarter(d):
return "Q%d_%d" % (math.ceil(d.month/3), d.year)
d = datetime.now()
print(d.strftime("%Y-%m-%d"), get_q(d))
d2 = d - timedelta(90)
print(d2.strftime("%Y-%m-%d"), get_q(d2))
d3 = d - timedelta(180 + 365)
print(d3.strftime("%Y-%m-%d"), get_q(d3))
And the output is:
2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017