是否有Python函数可确定日期在一年的哪个季度?


112

当然,我可以自己写这个,但是在我重新发明轮子之前,已经有一个已经做到这一点的功能了吗?


22
即使早期的答案似乎有点不屑一顾(“只是一个问题”,“看起来很简单”),问题还是非常有道理的:其中两个答案(包括一个被赞成的答案!)令人毛骨悚然,表明它并不是那么简单或“只是” ...
Alex Martelli

我确定他会回来修复此问题
Nadia Alramli 2009年

这个问题在2018年非常有帮助:D
wdfc

Answers:


161

给定一个实例xdatetime.date(x.month-1)//3会给你的四分之一(0第一季度,1第二季度,等等-加1,如果你需要从1计数,而不是;-)。


最初有两个答案,乘以赞成票,甚至最初被接受(目前都已删除),但有很多错误- -1除法前不做除法,而是除以4而不是3。从.month1到12,可以很容易地检查一下自己的公式是什么对:

for m in range(1, 13):
  print m//4 + 1,
print

给出1 1 1 2 2 2 2 3 3 3 3 4-两个四个月的季度和一个月的季度(深度)。

for m in range(1, 13):
  print (m-1)//3 + 1,
print

1 1 1 2 2 2 3 3 3 4 4 4-现在看起来这对您来说不是很可取吗?-)

我认为,这证明了这个问题是正确的;-)。

我认为datetime模块不一定应该具有所有可能有用的日历功能,但是我确实知道我在工作中维护了一个(经过测试;-)datetools模块来使用我的(以及其他人)项目,该模块几乎没有执行所有这些日历计算的函数-有些复杂,有些简单,但没有理由一遍又一遍地进行工作(甚至是简单的工作),也没有理由冒这样的错误;-)。


3
谢谢亚历克斯。这就是为什么应该有一个功能的原因。看看有多少人弄错了。
杰森·克里斯塔

我想你证明了你的观点。不必要重复评论来污染整个页面。
若昂·席尔瓦

1
@Jason,是的,正是-这就是为什么我看到其他错误答案(当前已删除)后就对您的问题进行投票,即使有人似乎已经对我的投票数进行了投票,嗯。
亚历克斯·马丁里

1
@JG,什么是“重复评论”?由于删除了错误的答案,注释就消失了,因此我将它们的内容带入了答案中-重要的是要意识到分散注意力或匆忙的容易程度,即使在简单的计算中也能避免可避免的错误,并且对最佳实践的编程有影响(就可重复使用的功能的制造和测试而言);这个案例是一个很好的例子(我认为证明这个问题是必要的)。
Alex Martelli

7
也可以使用:(m+2)//3代替(m-1)//3 + 1
2014年

48

如果您已经在使用pandas,则非常简单。

import datetime as dt
import pandas as pd

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

如果date数据框中有一列,则可以轻松创建一个新quarter列:

df['quarter'] = df['date'].dt.quarter

如果我的会计年度季度从9月开始怎么办?
亚瑟·豪兰

31

我会建议另一个可以说更清洁的解决方案。如果X是一个datetime.datetime.now()实例,则四分之一是:

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

必须从数学模块中导入ceil,因为它无法直接访问。


1
到目前为止最好的。万分感谢!
curlreggie

3
可能应该将其包装在int()中
Pablojim 2015年

就像@garbanzio一样,答案提示。我需要通过float函数输入month参数,以math.ceil(float(4)/3) = 2.0math.ceil(4/3) = 1.0
使它

1
别理我,我没意识到.3之后的情况。math.ceil(4/3.) = 2.0
Theo Kouzelis

11

对于试图获取会计年度季度(可能与日历年度有所不同)的任何人,我都编写了Python模块来执行此操作。

安装很简单。赶紧跑:

$ pip install fiscalyear

没有依赖关系,并且fiscalyear对Python 2和3都适用。

它基本上是内置的datetime模块的包装器,因此,datetime您已经熟悉的任何命令都可以使用。这是一个演示:

>>> 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托管在GitHubPyPI上。可以在“ 阅读文档”中找到文档。如果您正在寻找它当前没有的任何功能,请告诉我!


4

这是一个获取datetime.datetime对象并为每个季度返回唯一字符串的函数示例:

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

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

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

输出为:

2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017


2

此方法适用于任何映射:

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

我们刚刚生成了一个函数 int->int

month2quarter(9) # returns 3

这种方法也是万无一失的

month2quarter(-1) # returns None
month2quarter('July') # returns None

2

对于那些正在使用熊猫查询会计年度季度数据的人,

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

参考: 大熊猫时期指数


1

这是一个老问题,但仍然值得讨论。

这是我的解决方案,使用了出色的dateutil模块。

  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)

因此first_day,该季度的第一天也是该季度last_day的最后一天(通过找到下一个季度的第一天减去一天来计算)。


1

这非常简单,可以在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 = 'q'+str((now.month-1)//3+1)

0

嗯,所以计算可能会出错,这是一个更好的版本(仅出于此目的)

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]

在这种情况下,@ RussBradberry可能是您正确的选择,但有时可读性强并且被明确计数并导致更少的错误,而不是简单的计算
Anurag Uniyal 2013年

1
@RussBradberry还会看到已删除的答案和注释,看到简单的计算对于好的程序员来说也很棘手,除了测试之外,很难看到正确性,在我的解决方案中,您可以看到并确保它可以正常工作
Anurag Uniyal

1
就像你说的一样"it is difficult to see correctness except by testing it"。您应该像所有优秀的开发人员一样编写测试。测试可以帮助您避免犯错,并发现错误。开发人员切勿牺牲性能和可读性,以防止自己犯错。而且,这比您仅使用文字量编写静态字典时的可读性差。
Russ Bradberry

不要误会我的意思也不(m-1)//3 + 1是全部可读,没有多少人知道它是什么//。我最初的评论只是对我的说法"calculations can go wrong"听起来有些奇怪。
Russ Bradberry

@RussBradberry实际上,我同意您的回答,但我还是以其他方式代替,有时我看到很多代码,人们尝试计算/推导可以在地图中进行硬编码的内容
Anurag Uniyal 2013年

0

这是一个冗长但易读的解决方案,适用于datetime和date实例

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

0

使用字典,您可以通过

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))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.