Reputation: 12508
Sure I could write this myself, but before I go reinventing the wheel is there a function that already does this?
Upvotes: 163
Views: 213442
Reputation: 1487
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).
Upvotes: 2
Reputation: 1176
For those who are looking for financial year quarter data, using pandas,
import pandas as pd
today_date = pd.Timestamp.today()
quarter = pd.Period(today_date, freq='Q-MAR').strftime('Q%q')
quarter == 'Q4'
reference: pandas period index
Upvotes: 5
Reputation: 13700
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
Upvotes: 4
Reputation: 640
Below code is working for me!
df_test['Quarter'] = pd.PeriodIndex(df_test['DATE'], freq='Q')
df_test['Qtr'] = pddf_test['Quarter'].strftime('Q%q')
df_test['Day'] = pd.PeriodIndex(df_test['DATE'], freq='D').day
df_test = df_test[df_test['Day'] == 2].sort_values('DATE')
df_test
Output:
Upvotes: 2
Reputation: 4643
IF you are already using pandas
, it's quite simple: use the .quarter
attribute.
e.g. Timestamp.quarter
:
import pandas as pd
quarter = pd.Timestamp(2016, 2, 29).quarter
assert quarter == 1
If you have a date column in a dataframe, you can easily create a new quarter column with Series.dt.quarter
:
df['quarter'] = df['date'].dt.quarter
Upvotes: 82
Reputation: 3673
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
Upvotes: 6
Reputation: 1
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
Upvotes: -1
Reputation: 7715
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
Upvotes: 1
Reputation: 1175
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}'
Upvotes: 18
Reputation: 3481
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
Upvotes: 1
Reputation: 11
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)
Upvotes: 1
Reputation: 517
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))
Upvotes: 0
Reputation: 9782
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
Upvotes: 0
Reputation: 882123
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;-).
Upvotes: 235
Reputation: 2149
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!
Upvotes: 16
Reputation: 461
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.
Upvotes: 46
Reputation: 88827
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]
Upvotes: 0