Bir*_*lla 26 python python-2.7
我想生成一个包含两个日期之间所有月份的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
Run Code Online (Sandbox Code Playgroud)
atk*_*t12 42
我发现了一个非常简洁的方法来与熊猫一起做这件事,以防万一它可以帮助任何人:
更新:在这篇文章的帮助下,我把它归结为一个单行程:)
pd.date_range('2014-10-10','2016-01-07',
freq='MS').strftime("%Y-%b").tolist()
Run Code Online (Sandbox Code Playgroud)
老答案:
daterange = pd.date_range('2014-10-10','2016-01-07' , freq='1M')
daterange = daterange.union([daterange[-1] + 1])
daterange = [d.strftime('%y-%b') for d in daterange]
Run Code Online (Sandbox Code Playgroud)
第二行可防止最后一个日期从列表中删除.
sim*_*leo 30
>>> 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']
Run Code Online (Sandbox Code Playgroud)
更新:根据一条评论中的要求进行一些解释.这里有三个问题:将日期解析为适当的数据结构(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)
Run Code Online (Sandbox Code Playgroud)
在我的笔记本电脑上,我得到以下输出:
monthlist_short 2.3209939003
monthlist_fast 0.0774540901184
Run Code Online (Sandbox Code Playgroud)
简洁的实现速度大约慢30倍,因此我不建议在时间要求严格的应用程序中使用:)
import calendar
from datetime import *
date1 = datetime.strptime("2014-10-10", "%Y-%m-%d")
date2 = datetime.strptime("2016-01-07", "%Y-%m-%d")
date1 = date1.replace(day = 1)
date2 = date2.replace(day = 1)
months_str = calendar.month_name
months = []
while date1 < date2:
month = date1.month
year = date1.year
month_str = months_str[month][0:3]
months.append("{0}-{1}".format(month_str,str(year)[-2:]))
next_month = month+1 if month != 12 else 1
next_year = year + 1 if next_month == 1 else year
date1 = date1.replace( month = next_month, year= next_year)
print months
Run Code Online (Sandbox Code Playgroud)
此代码返回
['Oct-14', 'Nov-14', 'Dec-14', 'Jan-14', 'Feb-15', 'Mar-15', 'Apr-15', 'May-15', 'Jun-15', 'Jul-15', 'Aug-15', 'Sep-15', 'Oct-15', 'Nov-15', 'Dec-15', 'Jan-15']
Run Code Online (Sandbox Code Playgroud)
使用大熊猫,您可以使用一个像这样的衬垫:
import pandas as pd
date1 = "2014-10-10" # input start date
date2 = "2016-01-07" # input end date
month_list = [i.strftime("%b-%y") for i in pd.date_range(start=date1, end=date2, freq='MS')]
Run Code Online (Sandbox Code Playgroud)
这是我的解决方案,其中包含一个简单的列表理解,它用于range
了解月份必须在哪里开始和结束
from datetime import datetime as dt
sd = dt.strptime('2014-10-10', "%Y-%m-%d")
ed = dt.strptime('2016-01-07', "%Y-%m-%d")
lst = [dt.strptime('%2.2d-%2.2d' % (y, m), '%Y-%m').strftime('%b-%y') \
for y in xrange(sd.year, ed.year+1) \
for m in xrange(sd.month if y==sd.year else 1, ed.month+1 if y == ed.year else 13)]
print lst
Run Code Online (Sandbox Code Playgroud)
产生
['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']
Run Code Online (Sandbox Code Playgroud)
如果您有兴趣以 Python 格式保存日期,您可以尝试使用to_pydatetime()
.
import pandas as pd
from datetime import datetime
datemin = datetime(2010, 1, 1)
datemax = datetime(2019, 12, 31)
# First day of month
pd.date_range(datemin, datemax, freq='MS').to_pydatetime().tolist()
# Last day of month
pd.date_range(datemin, datemax, freq='M').to_pydatetime().tolist()
Run Code Online (Sandbox Code Playgroud)