在python中生成间隔之间的月份列表

发布于 2021-01-29 17:53:30

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

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
关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。
    >>> 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在将这些项保持正确顺序的同时将其删除。

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

    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)
    

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

    monthlist_short 2.3209939003
    monthlist_fast 0.0774540901184
    

    简洁的实现要慢30倍左右,因此我不建议在时间紧迫的应用程序中使用它:)



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看