在python中生成间隔之间的月份列表 [英] Generate list of months between interval in python

查看:77
本文介绍了在python中生成间隔之间的月份列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想生成一个包含两个日期之间发生的所有月份的python列表,输入和输出格式如下:

I want to generate a python list containing all months occurring between two dates, with the input and output formatted as follows:

date1 = "2014-10-10"  # input start date
date2 = "2016-01-07"  # input end date
month_list = ['Oct-14', 'Nov-14', 'Dec-14', 'Jan-15', 'Feb-15', 'Mar-15', 'Apr-15', 'May-15', 'Jun-15', 'Jul-15', 'Aug-15', 'Sep-15', 'Oct-15', 'Nov-15', 'Dec-15', 'Jan-16']  # output

推荐答案

>>> from datetime import datetime, timedelta
>>> from collections import OrderedDict
>>> dates = ["2014-10-10", "2016-01-07"]
>>> start, end = [datetime.strptime(_, "%Y-%m-%d") for _ in dates]
>>> OrderedDict(((start + timedelta(_)).strftime(r"%b-%y"), None) for _ in xrange((end - start).days)).keys()
['Oct-14', 'Nov-14', 'Dec-14', 'Jan-15', 'Feb-15', 'Mar-15', 'Apr-15', 'May-15', 'Jun-15', 'Jul-15', 'Aug-15', 'Sep-15', 'Oct-15', 'Nov-15', 'Dec-15', 'Jan-16']

更新:在一条评论中要求做一些解释.这里存在三个问题:将日期解析为适当的数据结构(strptime);获取给定两个极端和步骤(一个月)的日期范围;格式化输出日期 (strftime).datetime 类型重载了减法运算符,因此 end - start 是有意义的.结果是一个 timedelta 对象,表示两个日期之间的差异,而 .days 属性以天数表示此差异.没有 .months 属性,因此我们一次迭代一天并将日期转换为所需的输出格式.这会产生大量重复项,OrderedDict 会删除这些重复项,同时保持项目的正确顺序.

Update: a bit of explanation, as requested in one comment. There are three problems here: parsing the dates into appropriate data structures (strptime); getting the date range given the two extremes and the step (one month); formatting the output dates (strftime). The datetime type overloads the subtraction operator, so that end - start makes sense. The result is a timedelta object that represents the difference between the two dates, and the .days attribute gets this difference expressed in days. There is no .months attribute, so we iterate one day at a time and convert the dates to the desired output format. This yields a lot of duplicates, which the OrderedDict removes while keeping the items in the right order.

现在这很简单,因为它让 datetime 模块完成所有工作,但它也非常低效.我们每天都在调用很多方法,而我们只需要输出几个月.如果性能不是问题,上面的代码就可以了.否则,我们将不得不多做一些工作.让我们将上述实现与更高效的实现进行比较:

Now this is simple and concise because it lets the datetime module do all the work, but it's also horribly inefficient. We're calling a lot of methods for each day while we only need to output months. If performance is not an issue, the above code will be just fine. Otherwise, we'll have to work a bit more. Let's compare the above implementation with a more efficient one:

from datetime import datetime, timedelta
from collections import OrderedDict

dates = ["2014-10-10", "2016-01-07"]

def monthlist_short(dates):
    start, end = [datetime.strptime(_, "%Y-%m-%d") for _ in dates]
    return OrderedDict(((start + timedelta(_)).strftime(r"%b-%y"), None) for _ in xrange((end - start).days)).keys()

def monthlist_fast(dates):
    start, end = [datetime.strptime(_, "%Y-%m-%d") for _ in dates]
    total_months = lambda dt: dt.month + 12 * dt.year
    mlist = []
    for tot_m in xrange(total_months(start)-1, total_months(end)):
        y, m = divmod(tot_m, 12)
        mlist.append(datetime(y, m+1, 1).strftime("%b-%y"))
    return mlist

assert monthlist_fast(dates) == monthlist_short(dates)

if __name__ == "__main__":
    from timeit import Timer
    for func in "monthlist_short", "monthlist_fast":
        print func, Timer("%s(dates)" % func, "from __main__ import dates, %s" % func).timeit(1000)

在我的笔记本电脑上,我得到以下输出:

On my laptop, I get the following output:

monthlist_short 2.3209939003
monthlist_fast 0.0774540901184

简洁的实现大约慢 30 倍,所以我不建议在时间关键的应用程序中使用它 :)

The concise implementation is about 30 times slower, so I would not recommend it in time-critical applications :)

这篇关于在python中生成间隔之间的月份列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆