Is there a function to determine which quarter of the year a date is in?

Question:

Sure I could write this myself, but before I go reinventing the wheel is there a function that already does this?

Asked By: Jason Christa

||

Answers:

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;-).

Answered By: Alex Martelli

hmmm so calculations can go wrong, here is a better version (just for the sake of it)

first, second, third, fourth=1,2,3,4# you can make strings if you wish :)

quarterMap = {}
quarterMap.update(dict(zip((1,2,3),(first,)*3)))
quarterMap.update(dict(zip((4,5,6),(second,)*3)))
quarterMap.update(dict(zip((7,8,9),(third,)*3)))
quarterMap.update(dict(zip((10,11,12),(fourth,)*3)))

print quarterMap[6]
Answered By: Anurag Uniyal

I would suggest another arguably cleaner solution. If X is a datetime.datetime.now() instance, then the quarter is:

import math
Q=math.ceil(X.month/3.)

ceil has to be imported from math module as it can’t be accessed directly.

Answered By: Jonathan Rocher

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).

Answered By: MikeHoss

if m is the month number…

import math
math.ceil(float(m) / 3)
Answered By: garbanzio

IF you are already using pandas, it’s quite simple.

import datetime as dt
import pandas as pd

quarter = pd.Timestamp(dt.date(2016, 2, 29)).quarter
assert quarter == 1

If you have a date column in a dataframe, you can easily create a new quarter column:

df['quarter'] = df['date'].dt.quarter
Answered By: chishaku

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!

Answered By: Adam Stewart

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
Answered By: igniteflow

For those, who are looking for financial year quarter data,
using pandas,

import datetime
import pandas as pd
today_date = datetime.date.today()
quarter = pd.PeriodIndex(today_date, freq='Q-MAR').strftime('Q%q')

reference:
pandas period index

Answered By: Siddaram H

This method works for any mapping:

month2quarter = {
        1:1,2:1,3:1,
        4:2,5:2,6:2,
        7:3,8:3,9:3,
        10:4,11:4,12:4,
    }.get

We have just generated a function int->int

month2quarter(9) # returns 3

This method is also fool-proof

month2quarter(-1) # returns None
month2quarter('July') # returns None
Answered By: Uri Goren

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_quarter(d))

d2 = d - timedelta(90)
print(d2.strftime("%Y-%m-%d"), get_quarter(d2))

d3 = d - timedelta(180 + 365)
print(d3.strftime("%Y-%m-%d"), get_quarter(d3))

And the output is:

2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017
Answered By: Roei Bahumi

using dictionaries, you can pull this off by

def get_quarter(month):
    quarter_dictionary = {
        "Q1" : [1,2,3],
        "Q2" : [4,5,6],
        "Q3" : [7,8,9],
        "Q4" : [10,11,12]
    }

    for key,values in quarter_dictionary.items():
        for value in values:
            if value == month:
                return key

print(get_quarter(3))
Answered By: Led

This is very simple and works in python3:

from datetime import datetime

# Get current date-time.
now = datetime.now()

# Determine which quarter of the year is now. Returns q1, q2, q3 or q4.
quarter_of_the_year = f'q{(now.month-1)//3+1}'
Answered By: JavDomGom
for m in range(1, 13):
  print ((m*3)//10)
Answered By: akash

I tried the solution with x//3+1 and x//4+1,
We get incorrect quarter in either case.
The correct answer is like this

for i in range(1,13):
  print(((i-1)//3)+1) 
Answered By: Deepa
import datetime

def get_quarter_number_and_date_from_choices(p_quarter_choice):
"""
:param p_quarter_choice:
:return:
"""

current_date = datetime.date.today()
# current_quarter = current_date.month - 1 // 3 + 1
if p_quarter_choice == 'Q1':
    quarter = 1
    q_start_date = datetime.datetime(current_date.year, 3 * quarter - 2, 1)
    q_end_date = datetime.datetime(current_date.year, 3 * quarter + 1, 1) + datetime.timedelta(days=-1)
    return q_start_date, q_end_date
elif p_quarter_choice == 'Q2':
    quarter = 2
    q_start_date = datetime.datetime(current_date.year, 3 * quarter - 2, 1)
    q_end_date = datetime.datetime(current_date.year, 3 * quarter + 1, 1) + datetime.timedelta(days=-1)
    return q_start_date, q_end_date
elif p_quarter_choice == 'Q3':
    quarter = 3
    q_start_date = datetime.datetime(current_date.year, 3 * quarter - 2, 1)
    q_end_date = datetime.datetime(current_date.year, 3 * quarter + 1, 1) + datetime.timedelta(days=-1)
    return q_start_date, q_end_date
elif p_quarter_choice == 'Q4':
    quarter = 4
    q_start_date = datetime.datetime(current_date.year, 3 * quarter - 2, 1)
    q_end_date = datetime.datetime(current_date.year, 3 * quarter, 1) + datetime.timedelta(days=30)
    return q_start_date, q_end_date
return None
Answered By: Seenu S

A revisited solution using @Alex Martelli formula and creting a quick function as the question asks.

from datetime import timedelta, date

date_from = date(2021, 1, 1)
date_to = date(2021, 12, 31)

get_quarter = lambda dt: (dt.month-1)//3 + 1

quarter_from = get_quarter(date_from) 
quarter_to = get_quarter(date_to) 
print(quarter_from)
print(quarter_to)
# 1
# 4
Answered By: Federico Baù
def euclid(a,b):
    r = a % b
    q = int(  ( (a + b - 1) - (a - 1) % b ) / b  )
    return(q,r)

months_per_year = 12
months_per_quarter = 3

for i in range(months_per_year):
    print(i+1,euclid(i+1,months_per_quarter)[0])

#1 1
#2 1
#3 1
#4 2
#5 2
#6 2
#7 3
#8 3
#9 3
#10 4
#11 4
#12 4
Answered By: Igor Goldobin
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.