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

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

1

2

3date1 ="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

见我的答案在这里。 您可以在那里修改功能以满足您的需求。

我找到了一种非常简洁的方法来与Pandas进行共享,以防万一它对任何人都有帮助:

更新:在这篇文章的帮助下,我已经将它简化为一种形式:)

1

2pd.date_range('2014-10-10','2016-01-07',

freq='MS').strftime("%Y-%b").tolist()

旧答案:

1

2

3daterange = 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]

第二行防止最后一个日期从列表中删减。

我意识到更新的版本与tmsss的答案非常相似...请参阅下文。

1

2

3

4

5

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24from 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)

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

1

2monthlist_short 2.3209939003

monthlist_fast 0.0774540901184

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

看OP的预期输出

抱歉,我第一次读得很快。 香港专业教育学院修改答案,以实际解决这个问题:)

我印象深刻! 很好的答案

简直太棒了..正是我想要的。 最好也解释一下这些内容,这样其他观众也可以清楚地了解它@simleo

很好的解决方案。 我一直在寻找类似的东西一段时间。 许多其他解决方案并没有给我想要的结果。 天哪!

很好的解决方案,这节省了我很多时间!

您必须使用日历和日期时间

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18import 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

此代码返回

1['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']

我可以通过运行您的代码得到此信息:[Oct-1,Nov-1,Dec-1,Jan-1,Feb-1,Mar-1,Apr-1,May-1,Jun-1,Jul-1,Aug-1 -1、9月1日,10月1日,11月1日,12月1日,1月1日]

是!! 这是一个小错误。我写了str(year)[-2]而不是str(year)[-2:]。 固定! :)

使用大熊猫,您可以使用一个像这样的衬垫:

1

2

3

4

5

6import 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')]

如果您有兴趣以Python格式保存日期,则可以尝试使用to_pydatetime()。

1

2

3

4

5

6

7

8

9

10

11import 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()

偏移别名列表

在下面找到我使用拆分和基于模的简单迭代来解决此问题的方法,而无需导入任何特殊模块。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20date1 ="2014-10-10"

date2 ="2016-01-07"

y0 = int( date1.split('-')[0] ) # 2014

y1 = int( date2.split('-')[0] ) # 2016

m0 = int( date1.split('-')[1] ) - 1 # 10-1 --> 9 because will be used for indexing

m1 = int( date2.split('-')[1] ) - 1 # 01-1 --> 0 because will be used for indexing

months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

result = []

start = m0

for y in range(y0, y1+1):

for m in range(start,12):

result.append( str( months[m % 12])+'-'+str(y) )

if y == y1 and (m % 12) == m1:

break

start = 0

print result

$ python date.py

1['Oct-2014', 'Nov-2014', 'Dec-2014', 'Jan-2015', 'Feb-2015', 'Mar-2015', 'Apr-2015', 'May-2015', 'Jun-2015', 'Jul-2015', 'Aug-2015', 'Sep-2015', 'Oct-2015', 'Nov-2015', 'Dec-2015', 'Jan-2016']

之前做过类似的事情,所以我试图解决这个问题。使用不同的组件来执行此操作更加灵活,并使您可以针对不同用例将它们混合和匹配。正如您在iterate_months中的doctests所看到的那样,也可以通过这种方式更轻松地测试它们。

我也建议使用datetime.date对象作为输入,因为您可以对它们做更多的事情。为此,您必须首先解析您的输入字符串,但这很容易做到。

解析日期字符串

1

2

3

4

5

6

7

8def datify(date):

if isinstance(date, datetime.date):

return date

elif isinstance(date, datetime.datetime):

return date.date()

else:

# taken from simleo's answer

return datetime.strptime(date,"%Y-%m-%d")

首先,我们迭代了几个月

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34import datetime

def iterate_months(start_date, end_date):

"""Iterate monthly between two given dates.

Emitted will be the first day of each month.

>>> list(iterate_months(datetime.date(1999, 11, 1),

... datetime.date(2000, 2, 1)))

[datetime.date(1999, 11, 1), datetime.date(1999, 12, 1),\

datetime.date(2000, 1, 1), datetime.date(2000, 2, 1)]

"""

assert isinstance(start_date, datetime.date)

assert isinstance(end_date, datetime.date)

assert start_date < end_date

year = start_date.year

month = start_date.month

while True:

current = datetime.date(year, month, 1)

yield current

if current.month == end_date.month and current.year == end_date.year:

break

else:

month = ((month + 1) % 12) or 12

if month == 1:

year += 1

if __name__ == '__main__':

import doctest

doctest.testmod()

要格式化日期,请使用类似以下内容的格式

1

2def format_month(date):

return date.strftime(r"%b-%y")

放在一起

1

2

3

4

5start = datify("2014-10-10")

end = datify("2016-01-07")

for entry in iterate_months(start, end):

print format_month(entry)

或将其保存为列表:

1result = list(iterate_months(start, end))

这是我的解决方案,其中包含一个简单的列表理解功能,该列表使用range知道月份必须在哪里开始和结束

1

2

3

4

5

6

7

8

9from 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

产生

1['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']

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值