Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:所有月份都在范围内吗?_Python_Datetime - Fatal编程技术网

Python:所有月份都在范围内吗?

Python:所有月份都在范围内吗?,python,datetime,Python,Datetime,我想得到从现在到2010年8月的所有月份,格式如下: ['2010-08-01', '2010-09-01', .... , '2016-02-01'] 这就是我现在所拥有的: months = [] for y in range(2010, 2016): for m in range(1, 13): if (y == 2010) and m < 8: continue if (y == 2016) and m > 2

我想得到从现在到2010年8月的所有月份,格式如下:

['2010-08-01', '2010-09-01', .... , '2016-02-01']
这就是我现在所拥有的:

months = []
for y in range(2010, 2016):
    for m in range(1, 13):
        if (y == 2010) and m < 8:
            continue
        if (y == 2016) and m > 2:
            continue
        month = '%s-%s-01' % (y, ('0%s' % (m)) if m < 10 else m)
        months.append(month)
months=[]
对于范围内的y(2010年、2016年):
对于范围(1,13)内的m:
如果(y==2010)和m<8:
持续
如果(y==2016)和m>2:
持续
月份=“%s-%s-01%”(y,(“0%s%”(m)),如果m<10,则为m)
月。追加(月)

有什么更好的方法可以做到这一点呢?

您可以将
if
语句的数量减少到两行而不是四行,因为第二个
if
语句与前面的
if
语句做相同的事情有点多余

if (y == 2010 and m < 8) or (y == 2016 and m > 2):
    continue
如果(y==2010,m<8)或(y==2016,m>2):
持续

使用
datetime
timedelta
标准Python模块-无需安装任何新库

from datetime import datetime, timedelta

now = datetime(datetime.now().year, datetime.now().month, 1)
ctr = datetime(2010, 8, 1)
list = [ctr.strftime('%Y-%m-%d')]

while ctr <= now:
    ctr += timedelta(days=32)
    list.append( datetime(ctr.year, ctr.month, 1).strftime('%Y-%m-%d') )
从datetime导入datetime,timedelta
now=datetime(datetime.now().year,datetime.now().month,1)
ctr=日期时间(2010,8,1)
列表=[ctr.strftime(“%Y-%m-%d”)]
而ctr在这里很方便

作为练习,我省略了格式设置

from dateutil.relativedelta import relativedelta
import datetime

result = []

today = datetime.date.today()
current = datetime.date(2010, 8, 1)    

while current <= today:
    result.append(current)
    current += relativedelta(months=1)
从dateutil.relativedelta导入relativedelta
导入日期时间
结果=[]
今天=datetime.date.today()
当前=日期时间。日期(2010年8月1日)
虽然当前我不知道它是否更好,但像下面这样的方法可能会被认为更“pythonic”:

months = [
    '{}-{:0>2}-01'.format(year, month)
        for year in xrange(2010, 2016 + 1)
        for month in xrange(1, 12 + 1)
        if not (year <= 2010 and month < 8 or year >= 2016 and month > 2)
]
months=[
“{}-{:0>2}-01”。格式(年、月)
xrange年度(2010年、2016年+1年)
X范围内的月份(1,12+1)
如果没有(年份=2016,月份>2)
]
这里的主要区别是:

  • 当我们希望迭代生成一个列表时,使用a而不是在
    for
    循环中聚合列表元素
  • 使用的功能来指定,而不是明确区分10以下的数字和10及以上的数字
    • a(在
      {:0>2}
      占位符中的
      2
    • 右-(在
      {:0>2}
      占位符中的
    • 零-(在
      {:0>2}
      占位符中的
      0
  • xrange
    而不是
    range
    返回一个生成器,而不是列表,这样迭代值就可以在使用时生成,而不必保存在内存中。(对于这么小的范围没有关系,但在Python 2中习惯这一点是个好主意。)注意:在Python 3中,没有
    xrange
    ,并且
    range
    函数已经返回了一个生成器而不是列表
  • 明确上界的
    +1
    。这使得代码的人类读者更容易认识到,我们希望为将上限视为独占的方法(
    range
    xrange
    )指定一个包含性绑定。否则,他们可能会想13号是怎么回事

我查看了
dateutil
文档。事实证明,它提供了一种比使用
dateutil.relativedelta
:()

对于手头的任务,它与

from dateutil.rrule import *
from datetime import date

months = map(
    date.isoformat,
    rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())
)
精美的印刷品 注意,我们在这里有点作弊。
dateutil.rrule.rrule
生成的元素属于
datetime.datetime
类型,即使我们通过
dtstart
直到
类型为
datetime.date
,如上所述。我让
map
将它们提供给
date
isoformat
函数,该函数将它们转换为字符串,就好像它只是没有任何时间信息的日期一样

因此,看似等价的列表理解

[day.isoformat()
    for day in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]
将返回如下列表

['2010-08-01T00:00:00',
 '2010-09-01T00:00:00',
 '2010-10-01T00:00:00',
 '2010-11-01T00:00:00',
 ⋮
 '2015-12-01T00:00:00',
 '2016-01-01T00:00:00',
 '2016-02-01T00:00:00']
因此,如果我们想使用列表理解而不是
map
,我们必须执行以下操作

[dt.date().isoformat()
    for dt in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]

我找到了另一种使用datetime、timedelta和Calendar的方法:

from calendar import monthrange
from datetime import datetime, timedelta

def monthdelta(d1, d2):
    delta = 0
    while True:
        mdays = monthrange(d1.year, d1.month)[1]
        d1 += timedelta(days=mdays)
        if d1 <= d2:
            delta += 1
        else:
            break
    return delta

start_date = datetime(2016, 1, 1)
end_date = datetime(2016, 12, 1)

num_months = [i-12 if i>12 else i for i in range(start_date.month, monthdelta(start_date, end_date)+start_date.month+1)]
monthly_daterange = [datetime(start_date.year,i, start_date.day, start_date.hour) for i in num_months]
从日历导入monthrange
从datetime导入datetime,timedelta
def monthdelta(d1、d2):
增量=0
尽管如此:
mdays=monthrange(d1.年,d1.月)[1]
d1+=timedelta(天数=mdays)
如果d1 12中的其他i为范围内的i(开始日期.月份,月份)(开始日期,结束日期)+开始日期.月份+1)]
每月\日期范围=[日期时间(开始\日期.年,i,开始\日期.天,开始\日期.小时),对于i,单位为num \ u月]

一种不同的方法,不需要任何额外的库,也不需要嵌套或while循环。只需将您的日期转换为某个参考点的绝对月数(它实际上可以是任何日期,但为简单起见,我们可以使用0001年1月1日)。比如说

a=datetime.date(2010,2,5)
abs_months = a.year * 12 + a.month
一旦你有了一个代表你所在月份的数字,你可以简单地使用
range
来循环月份,然后再转换回:

广义问题的解决方案:

import datetime

def range_of_months(start_date, end_date):
    months = []
    for i in range(start_date.year * 12 + start_date.month, end_date.year*12+end_date.month + 1)
        months.append(datetime.date((i-13) // 12 + 1, (i-1) % 12 + 1, 1))
    return months
附加注释/说明:

import datetime

def range_of_months(start_date, end_date):
    months = []
    for i in range(start_date.year * 12 + start_date.month, end_date.year*12+end_date.month + 1)
        months.append(datetime.date((i-13) // 12 + 1, (i-1) % 12 + 1, 1))
    return months
这里,
/
将四舍五入除以最接近的整数,
%12
在除以12时给出余数,例如,
13%12
1


(还要注意,在上述
date.year*12+date.month
中,没有给出自0001年1月1日起的月数。例如,如果
date=datetime.datetime(1,1,1)
,然后
date.year*12+date.month
给出
13
。如果我想计算实际月数,我需要从年和月中减去1,但这只会使计算更加复杂。重要的是我们有一个一致的方法来转换和转换mont的整数表示形式h我们在这里。)

似乎有一种非常简单和干净的方法来实现这一点,方法是生成一个日期列表,并对每个月的第一天进行子集设置,如下例所示

import datetime
import pandas as pd

start_date = datetime.date(2010,8,1)
end_date = datetime.date(2016,2,1)

date_range = pd.date_range(start_date, end_date)
date_range = date_range[date_range.day==1]

print(date_range)

新鲜的蟒蛇一行从我这里

from dateutil.relativedelta import relativedelta
import datetime

[(start_date + relativedelta(months=+m)).isoformat() for m in range(0,relativedelta(start_date,end_date).months+1)] 


阿尼,这几乎是正确的,但你必须格式化日期