9

我正在寻找一种优雅且 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

但这似乎是不必要的迭代。

4

9 回答 9

19

您可以通过查看您收到的月份来“艰难地”做到这一点:

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)
于 2013-05-31T19:18:59.053 回答
4

使用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
于 2013-05-31T19:25:17.893 回答
2

利用所涉及的数据模式并将问题转化为表格查找 - 您的经典时空权衡

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])
于 2013-05-31T20:10:47.973 回答
1

几乎可以肯定,使用 pandas(python 库)会更开心,它有许多“业务时间”数据的功能。

http://pandas.pydata.org/pandas-docs/dev/timeseries.html

于 2013-05-31T19:15:02.943 回答
1

找出季度的第一天和第一个月,然后用relativedelta它减去一天。

from dateutil.relativedelta import relativedelta
def previous_quarter(ref):
    first_month_of_quarter = ((ref.month - 1) // 3) * 3 + 1
    return ref.replace(month=first_month_of_quarter, day=1) - relativedelta(days=1)  
于 2020-07-07T21:25:10.647 回答
1

为“下一季度”版本重新编写了Justin Ethier 的代码。还通过 pytz 和 strftime 格式添加了时区。@justin-ethier

import pytz
from datetime import datetime, timedelta
import datetime as dt

def nextQuarter():
    ref = datetime.now(pytz.timezone('America/New_York'))
    if ref.month < 4:
        next = dt.datetime(ref.year, 3, 31, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
    elif ref.month < 7:
        next = dt.datetime(ref.year, 6, 30, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
    elif ref.month < 10:
        next = dt.datetime(ref.year, 9, 30, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
    else:
        next = dt.datetime(ref.year + 1, 12, 31, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
    return next
next = nextQuarter()
于 2021-07-12T06:53:51.277 回答
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)
于 2014-01-30T09:29:22.337 回答
0

仅使用 python 的日期时间库的解决方案 -

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)
于 2016-07-21T11:05:43.947 回答
0

如果你想检索最后一个季度,你可以这样做

    if ref.month < 4:
        list1 = [datetime.date(ref.year - 1, 12, 31),
                            datetime.date(ref.year - 1, 9, 30),
                            datetime.date(ref.year - 1, 6, 30),
                            datetime.date(ref.year - 1, 3, 31)]

        list1 = [i.strftime('%Y%m%d') for i in list1]

        return list1

    elif ref.month < 7:
        return [datetime.date(ref.year, 3, 31),
                datetime.date(ref.year - 1, 12, 31),
                datetime.date(ref.year - 1, 9, 30),
                datetime.date(ref.year - 1, 6, 30)]
    elif ref.month < 10:
        return [datetime.date(ref.year, 6, 30),
                datetime.date(ref.year, 3, 31),
                datetime.date(ref.year - 1, 12, 31),
                datetime.date(ref.year - 1, 9, 30)]

    return [datetime.date(ref.year, 9, 30),
            datetime.date(ref.year, 6, 30),
            datetime.date(ref.year, 3, 30),
            datetime.date(ref.year - 1, 12, 31)]
于 2021-10-21T19:50:44.290 回答