我在python中得到了一个非常简单的东西:我需要从今天开始(包括(的过去 x 个月(year,month)
元组列表。因此,对于 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 的默认日期时间实现。我想出了以下解决方案:
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。此解决方案的问题:它需要更多的代码,而且也不是很好读。
那么如何才能正确地做到这一点呢?
我没有在任何地方看到它被记录下来,但是当给出超出范围(包括负(的月份值时,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)])
使用 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)]
最简洁的是使用整数除法(//
(和模(%
(函数,用自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 索引时,需要 months
表达式中的- 1
才能得到正确答案(即月从 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)]
更新:无论如何都要添加一个timedelta
版本,因为它看起来更漂亮:)
def get_years_months(start_date, months):
for i in range(months):
yield (start_date.year, start_date.month)
start_date -= datetime.timedelta(days=calendar.monthrange(start_date.year, start_date.month)[1])
您不需要使用timedelta
因为您只需要年份和月份,这是固定的。
def get_years_months(my_date, num_months):
cur_month = my_date.month
cur_year = my_date.year
result = []
for i in range(num_months):
if cur_month == 0:
cur_month = 12
cur_year -= 1
result.append((cur_year, cur_month))
cur_month -= 1
return result
if __name__ == "__main__":
import datetime
result = get_years_months(datetime.date.today(), 10)
print result
如果你创建一个函数来做日期数学运算,它几乎和你的原始实现一样好:
def next_month(this_year, this_month):
if this_month == 0:
return (this_year - 1, 12)
else:
return (this_year, this_month - 1)
this_month = datetime.date.today().month()
this_year = datetime.date.today().year()
for m in range(0, 10):
yield (this_year, this_month)
this_year, this_month = next_month(this_year, this_month)
如果你想在没有日期时间库的情况下做到这一点,你可以转换为自0年以来的月份,然后转换回来
end_year = 2014
end_month = 5
start_year = 2013
start_month = 7
print list = [(a/12,a % 12+1) for a in range(12*end_year+end_month-1,12*start_year+start_month-2,-1)]
Python 3 ( //
而不是 /
(:
list = [(a//12,a % 12+1) for a in range(12*end_year+end_month-1,12*start_year+start_month-2,-1)]
print(list)
[(2014, 5(, (2014, 4), (2014, 3), (2014, 2), (2014, 1), (2013, 12), (2013, 11), (2013, 10), (2013, 9), (2013, 8), (2013, 7(]
或者你可以定义一个函数来获取上个月,然后打印月份(有点简陋(
def last_month(year_month):#format YYYY-MM
aux = year_month.split('-')
m = int(aux[1])
y = int(aux[0])
if m-1 == 0:
return str(y-1)+"-12"
else:
return str(y)+"-"+str(m-1)
def print_last_month(ran, year_month= str(datetime.datetime.today().year)+'-'+str(datetime.datetime.today().month)):
i = 1
if ran != 10:
print( last_month(year_month) )
print_last_month(i+1, year_month= last_month(year_month))
def list_last_year_month(self):
last_day_of_prev_month = date.today()
number_of_years = self.number_of_years
time_list = collections.defaultdict(list)
for y in range(number_of_years+1):
for m in range(13):
last_day_of_prev_month = last_day_of_prev_month.replace(day=1) - timedelta(days=1)
last_month = str(last_day_of_prev_month.month)
last_year = str(last_day_of_prev_month.year)
time_list[last_year].append(last_month)
return time_list
使用日期时间和相对增量函数的简单解决方案。这将通过减去月数(输入(来返回过去的日期。此函数将返回完整日期,并使用以下函数可以分别获取年份和月份。
from datetime import date
from dateutil.relativedelta import relativedelta
def get_past_date(number_of_months):
return date.today() - relativedelta(months=number_of_months)
从日期获取年份
def get_year_from_the_date(date):
return date.year
从日期获取月份
def get_month_from_the_date(date):
return date.month