获取过去X个月的(年、月)

2024-05-17 07:34:40 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中我有一件很简单的事情要做: 我需要一个从今天开始(包括)的过去x个月的元组列表。因此,对于x=10和今天(2011年7月),命令应该输出:

[(2011, 7), (2011, 6), (2011, 5), (2011, 4), (2011, 3), 
(2011, 2), (2011, 1), (2010, 12), (2010, 11), (2010, 10)]

只应使用python的默认datetime实现。我想出了以下解决方案:

import datetime
[(d.year, d.month) for d in [datetime.date.today()-datetime.timedelta(weeks=4*i) for i in range(0,10)]]

这个解决方案为我的测试用例输出了正确的解决方案,但是我对这个解决方案并不满意:它假设一个月有四个星期,而这根本不是真的。我可以用days=30替换weeks=4,这样可以得到更好的解决方案,但仍然不正确。

我想到的另一个解决办法是用简单的数学,从月计数器中减去1,如果月计数器是0,则从年计数器中减去1。这个解决方案的问题是:它需要更多的代码,而且可读性也不强。

那么,如何才能正确地做到这一点呢?


Tags: inimport命令列表fortodaydatetimedate
3条回答

最简单的方法是使用integer division//)和modulus%)函数,用0年以来的月数表示月份:

months = year * 12 + month - 1 # Months since year 0 minus 1
tuples = [((months - i) // 12, (months - i) % 12 + 1) for i in range(10)]

当我们稍后将1添加到模函数的结果中以获得1索引时,需要- 1表达式中的months才能得到正确的答案(即月从1到12而不是0到11)。

或者您可能要创建生成器:

def year_month_tuples(year, month):
    months = year * 12 + month - 1 # -1 to reflect 1-indexing
    while True:
        yield (months // 12, months % 12 + 1) # +1 to reflect 1-indexing
        months -= 1 # next time we want the previous month

可用于:

>>> tuples = year_month_tuples(2011, 7)
>>> [tuples.next() for i in range(10)]

使用relativedelta。。。

import datetime
from dateutil.relativedelta import relativedelta

def get_last_months(start_date, months):
    for i in range(months):
        yield (start_date.year,start_date.month)
        start_date += relativedelta(months = -1)

>>> X = 10       
>>> [i for i in get_last_months(datetime.datetime.today(), X)]
>>> [(2013, 2), (2013, 1), (2012, 12), (2012, 11), (2012, 10), (2012, 9), (2012, 8), (2012, 7), (2012, 6), (2012, 5)]

我在任何地方都看不到它的文档,但是time.mktime如果超出范围(包括负的月份值),将“滚动”到正确的年份:

x = 10
now = time.localtime()
print([time.localtime(time.mktime((now.tm_year, now.tm_mon - n, 1, 0, 0, 0, 0, 0, 0)))[:2] for n in range(x)])

相关问题 更多 >