Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python获取当前日历季度的第一天和最后一天_Python_Python 2.7_Datetime - Fatal编程技术网

Python获取当前日历季度的第一天和最后一天

Python获取当前日历季度的第一天和最后一天,python,python-2.7,datetime,Python,Python 2.7,Datetime,我已经建立了一个函数来获取当前季度的第一天和最后一天,但是它有点冗长。我想知道,有没有更简洁的方法来实现这一点 我知道pandas有一个QuarterBegin()函数,但我无法以更简洁的方式实现它 import datetime as dt from dateutil.relativedelta import relativedelta def get_q(first=None,last=None): today = dt.date.today() qmonth

我已经建立了一个函数来获取当前季度的第一天和最后一天,但是它有点冗长。我想知道,有没有更简洁的方法来实现这一点

我知道
pandas
有一个
QuarterBegin()
函数,但我无法以更简洁的方式实现它

import datetime as dt
from dateutil.relativedelta import relativedelta     

def get_q(first=None,last=None):

    today = dt.date.today()

    qmonth = [1, 4, 7, 10]

    if first:
        for i,v in enumerate(qmonth):
            if (today.month-1)//3 == i:
                return dt.date(today.year,qmonth[i],1).strftime("%Y-%m-%d")

    if last:
        firstday = dt.datetime.strptime(get_q(first=True),"%Y-%m-%d") 
        lastday = firstday + relativedelta(months=3, days=-1)
        return lastday.strftime("%Y-%m-%d")


编辑:请告诉我这是否更适合

您可以这样做:

import bisect
import datetime as dt

def get_quarter_begin():
    today = dt.date.today()

    qbegins = [dt.date(today.year, month, 1) for month in (1,4,7,10)]

    idx = bisect.bisect(qbegins, today)
    return str(qbegins[idx-1])
这就解决了“第一”种情况;我把“最后一个”案例留作练习,但为了清晰起见,我建议将其作为一个独立的函数保留(对于您的原始版本,如果没有传递参数,会发生什么情况,这很奇怪!)。

  • 避免。不要将日期对象转换为字符串,而只是立即将其解析回日期对象,就像问题中的最后一个分支那样。相反,只在必要时返回日期对象并转换为字符串(访问对象属性,如
    .year
    .month
    ,比解析其字符串表示形式以提取相同信息更容易)
  • 避免相互排斥的布尔关键字参数(
    first
    last
    )。它是一个容易出错的接口,并且会导致代码重复。在这里很容易返回两个结果并访问相应的属性,例如
    。第一天
    之后。或者如果存在(不太可能的)性能问题;您可以创建两个函数,例如
    get\u first\u day\u of\u the\u quarter()
  • 为了简化算法,您可以在输入数据中添加一些冗余,例如,请参见下面代码中的
    quarter\u first\u days
    1
    在月份列表中提到了两次)-它允许无条件地使用
    i+1
#/usr/bin/env python
从集合导入namedtuple
从datetime导入MINYEAR、date、timedelta
天=时间增量(1)
季度第一天=[1,4,7,10,1]月份的日期(最小年+1,1,1)
季度=命名倍数(“季度”、“第一天”、“最后一天”)
def get_current_quarter():
今天=日期。今天()
i=(today.month-1)//3#获取季度指数
天=季度首天[i],季度首天[i+1]-天
返回季度(*[天.替换(年=今天.年)为天])
MINYEAR+1
用于容纳
-DAY
表达式(它假定
MINYEAR
)。季度指数公式来自

例如:

>>>获取当前季度()
季度(第一天=日期时间日期(2016年4月1日),最后一天=日期时间日期(2016年6月30日))
>>>str(获取当前季度().最后一天)
'2016-06-30'
为什么这么复杂:-)

为什么要自己滚

import pandas as pd

quarter_start = pd.to_datetime(pd.datetime.today() - pd.tseries.offsets.QuarterBegin(startingMonth=1)).date()

您不需要使用不必要的循环或像pandas这样的大型库来实现这一点。您可以使用简单的整数除法/算术和datetime库(尽管使用dateutil会产生更干净的代码)

输出:

>>> d1=datetime.date(2017,2,15)
>>> d2=datetime.date(2017,1,1)
>>> d3=datetime.date(2017,10,1)
>>> d4=datetime.date(2017,12,31)
>>> 
>>> getQuarterStart(d1)
datetime.date(2017, 1, 1)
>>> getQuarterStart(d2)
datetime.date(2017, 1, 1)
>>> getQuarterStart(d3)
datetime.date(2017, 10, 1)
>>> getQuarterStart(d4)
datetime.date(2017, 10, 1)
>>> getQuarterEnd1(d1)
datetime.date(2017, 3, 31)
>>> getQuarterEnd1(d2)
datetime.date(2017, 3, 31)
>>> getQuarterEnd1(d3)
datetime.date(2017, 12, 31)
>>> getQuarterEnd1(d4)
datetime.date(2017, 12, 31)
>>> getQuarterEnd2(d1)
datetime.date(2017, 3, 31)
>>> getQuarterEnd2(d2)
datetime.date(2017, 3, 31)
>>> getQuarterEnd2(d3)
datetime.date(2017, 12, 31)
>>> getQuarterEnd2(d4)
datetime.date(2017, 12, 31)

为什么
relativedelta(月=3)-dt.timedelta(天=1)
而不是
relativedelta(月=3,天=-1)
?@Paul-是的,这样更好。非常感谢。我会编辑这篇文章。如果你确实返回了一个日期对象而不是字符串,这会使函数更通用。@J.F.Sebastian:我完全同意——我是按照OP的做法来建模的。但是是的,删除return语句中的
str()
调用对我来说也更可取。无关:对于一个小的
N
(例如在本例中),可以使用线性搜索而不是二进制搜索:
return next(date(date.year,month,1)for month,next_month in zip(quarty_months,quarty_months[1:])如果今天.month
其中
季度月=[1,4,7,10,13]
。虽然这里的微优化可能没有意义,但任何可读的解决方案都可以。@JohnZwinck-这是一个非常有趣和优雅的答案-谢谢你的发帖。我以前从未听说过对分模块。我想我可以找出如何完成和等效于“最后一个”:)只是出于兴趣,在一个功能中有两个功能有什么问题,如果我的函数在没有传递参数的情况下什么也不返回,那又有什么问题呢?@Charon:一个函数使用参数来产生完全不同的功能,通常不如两个单独的函数清晰。例如,Python内置了
min()
max()
,而不是
minormax(min=False,max=False)
。感谢您发布此答案。我可以看出,最好只使用
date
对象,然后仅在必要时将它们转换为字符串。我想我会把你们的答案和上面的答案结合起来,形成我的函数。如何计算当前的季度结束日期?将QuarterBegin更改为QuarterEnd,并用加法代替减法。感谢在开始月份也做了一个更改=3
import datetime

def getQuarterStart(dt=datetime.date.today()):
    return datetime.date(dt.year, (dt.month - 1) // 3 * 3 + 1, 1)

# using just datetime
def getQuarterEnd1(dt=datetime.date.today()):
    nextQtYr = dt.year + (1 if dt.month>9 else 0)
    nextQtFirstMo = (dt.month - 1) // 3 * 3 + 4
    nextQtFirstMo = 1 if nextQtFirstMo==13 else nextQtFirstMo
    nextQtFirstDy = datetime.date(nextQtYr, nextQtFirstMo, 1)
    return nextQtFirstDy - datetime.timedelta(days=1)

# using dateutil
from dateutil.relativedelta import relativedelta

def getQuarterEnd2(dt=datetime.date.today()):
    quarterStart = getQuarterStart(dt)
    return quarterStart + relativedelta(months=3, days=-1)
>>> d1=datetime.date(2017,2,15)
>>> d2=datetime.date(2017,1,1)
>>> d3=datetime.date(2017,10,1)
>>> d4=datetime.date(2017,12,31)
>>> 
>>> getQuarterStart(d1)
datetime.date(2017, 1, 1)
>>> getQuarterStart(d2)
datetime.date(2017, 1, 1)
>>> getQuarterStart(d3)
datetime.date(2017, 10, 1)
>>> getQuarterStart(d4)
datetime.date(2017, 10, 1)
>>> getQuarterEnd1(d1)
datetime.date(2017, 3, 31)
>>> getQuarterEnd1(d2)
datetime.date(2017, 3, 31)
>>> getQuarterEnd1(d3)
datetime.date(2017, 12, 31)
>>> getQuarterEnd1(d4)
datetime.date(2017, 12, 31)
>>> getQuarterEnd2(d1)
datetime.date(2017, 3, 31)
>>> getQuarterEnd2(d2)
datetime.date(2017, 3, 31)
>>> getQuarterEnd2(d3)
datetime.date(2017, 12, 31)
>>> getQuarterEnd2(d4)
datetime.date(2017, 12, 31)