有没有一个函数可以确定日期属于一年的哪个季度?

156

我可以自己编写这个功能,但在我重复造轮子之前,是否已经有一个现成的函数可以实现这个功能?


2
如果日期时间对象存储在 Pandas Series 或 Dataframe 中,则有一种方法可以返回相应的季度:pandas.Series.dt.quarter - Sumax
18个回答

229

给定一个 datetime.date 的实例 x(x.month-1)//3 将给你所在的季度(第一季度为0,第二季度为1,以此类推 -- 如果需要从1开始计数,则需加1;-)。


最初的两个答案(现已被删除),虽然被多次投票,甚至被采纳,但存在缺陷 -- 没有执行除法前的减 1 操作,而且将除数设为了 4 而不是 3。由于 .month 的值为 1 至 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 模块,供我的(和其他人的)项目使用,其中有许多小函数执行所有这些日期计算 - 有些复杂,有些简单,但没有理由重复地做这项工作(即使是简单工作),或者冒着出现计算错误的风险;-)。


4
谢谢,Alex。这就是为什么应该有一个函数。看看有多少人搞错了。 - Jason Christa
1
@Jason,没错 - 这就是为什么我在看到其他有漏洞的答案(现在已被删除)后点赞了您的问题,尽管其他人似乎对我的点赞进行了反对,呵呵。 - Alex Martelli
2
@JG,“重复的评论”是什么意思?由于有缺陷的答案已被删除,因此评论也随之消失,所以我将它们的内容带入了答案中——重要的是要意识到即使在简单的计算中也很容易分心或匆忙并产生可避免的错误,并且这对于编程最佳实践(例如制作和彻底测试可重用函数)具有后果;这种情况是一个很好的例子(我认为证明了这个问题是有必要的)。 - Alex Martelli
@myroslav,我还没有开源它,但如果有需求的话,这并不难,例如它可以作为http://code.google.com/p/just-the-time/的一部分。你对哪些部分感兴趣? - Alex Martelli
8
可以使用(m+2)//3代替(m-1)//3 + 1。 - Ben
显示剩余4条评论

78

如果你已经在使用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

如果我的财政年度季度从九月开始呢? - Arthur D. Howland
Pandas方法pandas.Series.dt.quarter是一个理想的解决方案,当您在DataframeSeries对象中具有日期时间值时。 - Sumax

46

我会提供另一个可能更加简洁的解决方案。如果X是datetime.datetime.now()实例,那么季度是:

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

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


1
到目前为止最好的。非常感谢! - curlyreggie
3
可能需要用int()将其包装。 - Pablojim
就像@garbanzio的回答所建议的那样。我需要通过float函数将月份参数传递以使其正常工作math.ceil(float(4)/3) = 2.0,而math.ceil(4/3) = 1.0 - Theo Kouzelis
1
忽略我,我没有意识到3后面的“。”。 math.ceil(4/3.) = 2.0 - Theo Kouzelis

16

如果有人想要获取财政年度的季度,这可能与日历年度不同,我编写了一个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上。文档可在Read the Docs找到。如果你需要任何当前没有的功能,请告诉我!


15

这很简单,适用于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}'

8

如果m是月份数字...

import math
math.ceil(float(m) / 3)

如果你手头有月份,这就非常简单了,这是天才的做法。 - Arun Mohan

6
这里是一个函数示例,它获取一个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_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))

输出结果为:

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

5

对于那些正在寻找财年季度数据的人,可以使用pandas进行操作。

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

参考链接: pandas 时期索引


5

这种方法适用于任何映射:

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
这是一个老问题,但仍值得讨论。
以下是我的解决方案,使用了优秀的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 是本季度的最后一天(通过找到下个季度的第一天减去一天来计算)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接