2013-05-31 88 views
3

我正在尋找一種優雅和pythonic的方式來獲得上一季度結束的日期。計算上一季度結束

事情是這樣的:

def previous_quarter(reference_date): 
    ... 


>>> previous_quarter(datetime.date(2013, 5, 31)) 
datetime.date(2013, 3, 31) 

>>> previous_quarter(datetime.date(2013, 2, 1)) 
datetime.date(2012, 12, 31) 

>>> previous_quarter(datetime.date(2013, 3, 31)) 
datetime.date(2012, 12, 31) 

>>> previous_quarter(datetime.date(2013, 11, 1)) 
datetime.date(2013, 9, 30) 

編輯:我曾嘗試什麼嗎?

是的,這似乎工作:

def previous_quarter(ref_date): 
    current_date = ref_date - timedelta(days=1) 
    while current_date.month % 3: 
     current_date -= timedelta(days=1) 
    return current_date 

但似乎不必要的迭代。

+1

你嘗試過什麼? – martineau

+0

@martineau:見編輯。 – dgel

+0

看看我的解決方案,如果'ref_date.month'可以被3整除...... – dgel

回答

5

你可以做到的 「硬辦法」 通過看這個月您將收到:

def previous_quarter(ref): 
    if ref.month < 4: 
     return datetime.date(ref.year - 1, 12, 31) 
    elif ref.month < 7: 
     return datetime.date(ref.year, 3, 31) 
    elif ref.month < 10: 
     return datetime.date(ref.year, 6, 30) 
    return datetime.date(ref.year, 9, 30) 
+1

我喜歡它 - 乾淨,簡單,有效。 – dgel

2

使用dateutil

import datetime as DT 
import dateutil.rrule as rrule 

def previous_quarter(date): 
    date = DT.datetime(date.year, date.month, date.day) 
    rr = rrule.rrule(
     rrule.DAILY, 
     bymonth=(3,6,9,12), # the month must be one of these 
     bymonthday=-1,   # the day has to be the last of the month 
     dtstart = date-DT.timedelta(days=100)) 
    result = rr.before(date, inc=False) # inc=False ensures result < date 
    return result.date() 

print(previous_quarter(DT.date(2013, 5, 31))) 
# 2013-03-31 
print(previous_quarter(DT.date(2013, 2, 1))) 
# 2012-12-31 
print(previous_quarter(DT.date(2013, 3, 31))) 
# 2012-12-31 
print(previous_quarter(DT.date(2013, 11, 1))) 
# 2013-09-30 
1

開拓所涉及的數據模式和將問題轉化爲表格查詢 - 您的經典space-time tradeff

只使用python的 datetime
from datetime import date 

PQTBL = (((12,31,-1),)*3 + ((3,31,0),)*3 + ((6,30,0),)*3 + ((9,30,0),)*3) 

def previous_quarter(ref): 
    entry = PQTBL[ref.month-1] 
    return date(ref.year-entry[2], entry[0], entry[1]) 
+0

應該是:'返回日期(ref.year + entry [2],entry [0],entry [1])'(應該改變標誌) – Gerrat

0
import datetime 
def previous_quarter(ref): 
    quarter = (ref.month - 1) // 3 
    prev_quarter = (quarter - 1) % 4 
    return datetime.datetime(ref.year if quarter>0 else ref.year-1, prev_quarter*3+1, 1) 
0

解決方案 -

import datetime 

def get_quarter_end(dt): 
    ''' 
     given a datetime object, find the end of the quarter 
    ''' 
    quarter_of_month = int((dt.month-1)/3 + 1) 
    #====================================================== 
    # find the first day of the next quarter 
    #====================================================== 
    # if in last quarter then go to the next year 
    year = dt.year + 1 if quarter_of_month==4 else dt.year 
    # if in last quarter then month is january (or 1) 
    month = 1 if quarter_of_month==4 else (quarter_of_month*3) + 1 

    first_of_next_quarter = datetime.datetime(year = year, 
               month = month, 
               day = 1 
              ) 
    # last day of quarter for dt will be minus 1 day of first of next quarter 
    quarter_end_dt = first_of_next_quarter - datetime.timedelta(days=1) 
    return quarter_end_dt 

if __name__=='__main__': 
    dt = datetime.datetime.strptime('2016-07-15', '%Y-%m-%d') 
    target_dt = get_quarter_end(dt)