Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.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_Date_Datetime_Iteration_Date Range - Fatal编程技术网

在Python中迭代一系列日期

在Python中迭代一系列日期,python,date,datetime,iteration,date-range,Python,Date,Datetime,Iteration,Date Range,我有下面的代码来做这件事,但是我怎样才能做得更好呢?现在我认为它比嵌套循环好,但是当您在列表中有一个生成器时,它开始得到Perl一行 day\u count=(结束日期-开始日期)。days+1 如果d为什么有两个嵌套迭代?对于我来说,它只在一次迭代中生成相同的数据列表: for single_date in (start_date + timedelta(n) for n in range(day_count)): print ... 并且没有存储任何列表,只对一个生成器进行迭代。而

我有下面的代码来做这件事,但是我怎样才能做得更好呢?现在我认为它比嵌套循环好,但是当您在列表中有一个生成器时,它开始得到Perl一行

day\u count=(结束日期-开始日期)。days+1

如果d为什么有两个嵌套迭代?对于我来说,它只在一次迭代中生成相同的数据列表:

for single_date in (start_date + timedelta(n) for n in range(day_count)):
    print ...
并且没有存储任何列表,只对一个生成器进行迭代。而且生成器中的“if”似乎没有必要

毕竟,一个线性序列应该只需要一个迭代器,而不是两个

与John Machin讨论后更新: 也许最优雅的解决方案是使用生成器函数完全隐藏/抽象日期范围内的迭代:

from datetime import date, timedelta

def daterange(start_date, end_date):
    for n in range(int((end_date - start_date).days)):
        yield start_date + timedelta(n)

start_date = date(2013, 1, 1)
end_date = date(2015, 6, 2)
for single_date in daterange(start_date, end_date):
    print(single_date.strftime("%Y-%m-%d"))

注意:为了与内置的
range()
函数保持一致,此迭代在到达
结束日期之前停止。因此,对于包含性迭代,请使用第二天,就像使用
range()

一样,这可能更清楚:

from datetime import date, timedelta

start_date = date(2019, 1, 1)
end_date = date(2020, 1, 1)
delta = timedelta(days=1)
while start_date <= end_date:
    print(start_date.strftime("%Y-%m-%d"))
    start_date += delta
from datetime导入日期,timedelta
开始日期=日期(2019年1月1日)
结束日期=日期(2020年1月1日)
增量=时间增量(天数=1)
开始日期<代码>导入日期时间时
def daterange(开始、停止、步骤=datetime.TIMEDTA(天=1),包括=False):
#inclusive=False,默认情况下表现类似于range
如果step.days>0:
启动<停止时:
产量起点
开始=开始+步骤
#不是+=!如果传入的对象是可变的,则不要修改它
#由于此功能不限于
#仅datetime模块中的类型
elif步骤天数<0:
启动>停止时:
产量起点
开始=开始+步骤
如果包含且开始==停止:
产量起点
# ...
对于daterange中的日期(开始日期、结束日期,包括=True):
打印strftime(“%Y-%m-%d”,date.timetuple())
通过支持负阶跃等,此函数的功能超出了您严格要求的范围。只要您将范围逻辑考虑在内,就不需要单独的
日计数
,最重要的是,当您从多个位置调用函数时,代码变得更容易阅读。

使用库:

此python库具有许多更高级的功能,其中一些非常有用,例如
相对增量
s-并作为单个文件(模块)实现,可以轻松地包含在项目中。

import datetime
import datetime

def daterange(start, stop, step_days=1):
    current = start
    step = datetime.timedelta(step_days)
    if step_days > 0:
        while current < stop:
            yield current
            current += step
    elif step_days < 0:
        while current > stop:
            yield current
            current += step
    else:
        raise ValueError("daterange() step_days argument must not be zero")

if __name__ == "__main__":
    from pprint import pprint as pp
    lo = datetime.date(2008, 12, 27)
    hi = datetime.date(2009, 1, 5)
    pp(list(daterange(lo, hi)))
    pp(list(daterange(hi, lo, -1)))
    pp(list(daterange(lo, hi, 7)))
    pp(list(daterange(hi, lo, -7))) 
    assert not list(daterange(lo, hi, -1))
    assert not list(daterange(hi, lo))
    assert not list(daterange(lo, hi, -7))
    assert not list(daterange(hi, lo, 7)) 
def日期范围(开始、停止、步骤天数=1): 电流=启动 步长=datetime.timedelta(步长天数) 如果步骤天>0: 当电流<停止时: 屈服电流 电流+=阶跃 elif步骤天数<0: 当前>停止时: 屈服电流 电流+=阶跃 其他: raise VALUERROR(“daterange()步骤\天数参数不能为零”) 如果名称=“\uuuuu main\uuuuuuuu”: 从pprint导入pprint作为pp lo=日期时间。日期(2008年12月27日) hi=datetime.date(2009年1月5日) pp(列表(日期范围(lo,hi))) pp(列表(日期范围(hi,lo,-1))) pp(列表(日期范围(lo,hi,7))) pp(列表(日期范围(hi,lo,-7))) 断言非列表(日期范围(lo,hi,-1)) 断言非列表(日期范围(hi,lo)) 断言非列表(日期范围(lo,hi,-7)) 断言非列表(日期范围(hi、lo、7))
范围内的i(16):
打印datetime.date.today()+datetime.timedelta(天=i)

对于按天递增的范围,以下内容如何:

for d in map( lambda x: startDate+datetime.timedelta(days=x), xrange( (stopDate-startDate).days ) ):
  # Do stuff here
  • startDate和stopDate是datetime.date对象
对于通用版本:

for d in map( lambda x: startTime+x*stepTime, xrange( (stopTime-startTime).total_seconds() / stepTime.total_seconds() ) ):
  # Do stuff here
  • startTime和stopTime是datetime.date或datetime.datetime对象 (两者应为同一类型)
  • stepTime是一个timedelta对象
请注意,只有在python 2.7之后才支持.total_seconds(),如果您仍使用早期版本,则可以编写自己的函数:

def total_seconds( td ):
  return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
为什么不试试:

import datetime as dt

start_date = dt.datetime(2012, 12,1)
end_date = dt.datetime(2012, 12,5)

total_days = (end_date - start_date).days + 1 #inclusive 5 days

for day_number in range(total_days):
    current_date = (start_date + dt.timedelta(days = day_number)).date()
    print current_date

一般来说,熊猫是时间序列的最佳选择,它直接支持日期范围

import pandas as pd
daterange = pd.date_range(start_date, end_date)
然后,您可以在日期范围内循环以打印日期:

for single_date in daterange:
    print (single_date.strftime("%Y-%m-%d"))
它还提供了许多选项,使生活更轻松。例如,如果您只想要工作日,您只需在bdate_范围内进行交换。请参阅

Pandas的强大之处在于它的数据帧,它支持矢量化操作(与numpy非常相似),使得跨大量数据的操作非常快速和简单

编辑: 您也可以完全跳过for循环,直接打印,这样更容易、更高效:

print(daterange)

此功能有一些额外的功能:

  • 可以为开始或结束传递与日期\格式匹配的字符串,并将其转换为日期对象
  • 可以为开始或结束传递日期对象
  • 如果结束时间早于开始时间,则检查错误

    import datetime
    from datetime import timedelta
    
    
    DATE_FORMAT = '%Y/%m/%d'
    
    def daterange(start, end):
          def convert(date):
                try:
                      date = datetime.datetime.strptime(date, DATE_FORMAT)
                      return date.date()
                except TypeError:
                      return date
    
          def get_date(n):
                return datetime.datetime.strftime(convert(start) + timedelta(days=n), DATE_FORMAT)
    
          days = (convert(end) - convert(start)).days
          if days <= 0:
                raise ValueError('The start date must be before the end date.')
          for n in range(0, days):
                yield get_date(n)
    
    
    start = '2014/12/1'
    end = '2014/12/31'
    print list(daterange(start, end))
    
    start_ = datetime.date.today()
    end = '2015/12/1'
    print list(daterange(start, end))
    
    导入日期时间
    从日期时间导入时间增量
    日期\格式=“%Y/%m/%d”
    def日期范围(开始、结束):
    def转换(日期):
    尝试:
    date=datetime.datetime.strtime(日期,日期格式)
    返回日期。日期()
    除类型错误外:
    返回日期
    def获取日期(n):
    return datetime.datetime.strftime(转换(开始)+timedelta(天数=n),日期格式)
    天=(转换(结束)-转换(开始))。天
    
    如果天数显示从今天开始的最后n天:

    import datetime
    for i in range(0, 100):
        print((datetime.date.today() + datetime.timedelta(i)).isoformat())
    
    输出:

    2016-06-29
    2016-06-30
    2016-07-01
    2016-07-02
    2016-07-03
    2016-07-04
    

    Numpy的
    arange
    功能可应用于日期:

    import numpy as np
    from datetime import datetime, timedelta
    d0 = datetime(2009, 1,1)
    d1 = datetime(2010, 1,1)
    dt = timedelta(days = 1)
    dates = np.arange(d0, d1, dt).astype(datetime)
    

    astype
    的用途是将
    numpy.datetime64
    转换为
    datetime.datetime
    对象数组。

    以下是通用日期范围函数的代码,类似于Ber的答案,但更灵活:

    def count_timedelta(delta, step, seconds_in_interval):
        """Helper function for iterate.  Finds the number of intervals in the timedelta."""
        return int(delta.total_seconds() / (seconds_in_interval * step))
    
    
    def range_dt(start, end, step=1, interval='day'):
        """Iterate over datetimes or dates, similar to builtin range."""
        intervals = functools.partial(count_timedelta, (end - start), step)
    
        if interval == 'week':
            for i in range(intervals(3600 * 24 * 7)):
                yield start + datetime.timedelta(weeks=i) * step
    
        elif interval == 'day':
            for i in range(intervals(3600 * 24)):
                yield start + datetime.timedelta(days=i) * step
    
        elif interval == 'hour':
            for i in range(intervals(3600)):
                yield start + datetime.timedelta(hours=i) * step
    
        elif interval == 'minute':
            for i in range(intervals(60)):
                yield start + datetime.timedelta(minutes=i) * step
    
        elif interval == 'second':
            for i in range(intervals(1)):
                yield start + datetime.timedelta(seconds=i) * step
    
        elif interval == 'millisecond':
            for i in range(intervals(1 / 1000)):
                yield start + datetime.timedelta(milliseconds=i) * step
    
        elif interval == 'microsecond':
            for i in range(intervals(1e-6)):
                yield start + datetime.timedelta(microseconds=i) * step
    
        else:
            raise AttributeError("Interval must be 'week', 'day', 'hour' 'second', \
                'microsecond' or 'millisecond'.")
    

    这是我能想到的最人性化的解决方案

    import datetime
    
    def daterange(start, end, step=datetime.timedelta(1)):
        curr = start
        while curr < end:
            yield curr
            curr += step
    
    导入日期时间
    def daterange(开始、结束、步骤=datetime.timedelta(1)):
    curr=开始
    当前<结束时:
    收益率货币
    电流+=步进
    
    我也有类似的问题,但我需要每月迭代,而不是每天迭代。
    def count_timedelta(delta, step, seconds_in_interval):
        """Helper function for iterate.  Finds the number of intervals in the timedelta."""
        return int(delta.total_seconds() / (seconds_in_interval * step))
    
    
    def range_dt(start, end, step=1, interval='day'):
        """Iterate over datetimes or dates, similar to builtin range."""
        intervals = functools.partial(count_timedelta, (end - start), step)
    
        if interval == 'week':
            for i in range(intervals(3600 * 24 * 7)):
                yield start + datetime.timedelta(weeks=i) * step
    
        elif interval == 'day':
            for i in range(intervals(3600 * 24)):
                yield start + datetime.timedelta(days=i) * step
    
        elif interval == 'hour':
            for i in range(intervals(3600)):
                yield start + datetime.timedelta(hours=i) * step
    
        elif interval == 'minute':
            for i in range(intervals(60)):
                yield start + datetime.timedelta(minutes=i) * step
    
        elif interval == 'second':
            for i in range(intervals(1)):
                yield start + datetime.timedelta(seconds=i) * step
    
        elif interval == 'millisecond':
            for i in range(intervals(1 / 1000)):
                yield start + datetime.timedelta(milliseconds=i) * step
    
        elif interval == 'microsecond':
            for i in range(intervals(1e-6)):
                yield start + datetime.timedelta(microseconds=i) * step
    
        else:
            raise AttributeError("Interval must be 'week', 'day', 'hour' 'second', \
                'microsecond' or 'millisecond'.")
    
    import datetime
    
    def daterange(start, end, step=datetime.timedelta(1)):
        curr = start
        while curr < end:
            yield curr
            curr += step
    
    import calendar
    from datetime import datetime, timedelta
    
    def days_in_month(dt):
        return calendar.monthrange(dt.year, dt.month)[1]
    
    def monthly_range(dt_start, dt_end):
        forward = dt_end >= dt_start
        finish = False
        dt = dt_start
    
        while not finish:
            yield dt.date()
            if forward:
                days = days_in_month(dt)
                dt = dt + timedelta(days=days)            
                finish = dt > dt_end
            else:
                _tmp_dt = dt.replace(day=1) - timedelta(days=1)
                dt = (_tmp_dt.replace(day=dt.day))
                finish = dt < dt_end
    
    date_start = datetime(2016, 6, 1)
    date_end = datetime(2017, 1, 1)
    
    for p in monthly_range(date_start, date_end):
        print(p)
    
    2016-06-01
    2016-07-01
    2016-08-01
    2016-09-01
    2016-10-01
    2016-11-01
    2016-12-01
    2017-01-01
    
    date_start = datetime(2017, 1, 1)
    date_end = datetime(2016, 6, 1)
    
    for p in monthly_range(date_start, date_end):
        print(p)
    
    2017-01-01
    2016-12-01
    2016-11-01
    2016-10-01
    2016-09-01
    2016-08-01
    2016-07-01
    2016-06-01
    
    import pandas as pd
    
    print pd.date_range(start='1/1/2010', end='1/08/2018', freq='M')
    
    > pip install DateTimeRange
    
    from datetimerange import DateTimeRange
    
    def dateRange(start, end, step):
            rangeList = []
            time_range = DateTimeRange(start, end)
            for value in time_range.range(datetime.timedelta(days=step)):
                rangeList.append(value.strftime('%m/%d/%Y'))
            return rangeList
    
        dateRange("2018-09-07", "2018-12-25", 7)  
    
        Out[92]: 
        ['09/07/2018',
         '09/14/2018',
         '09/21/2018',
         '09/28/2018',
         '10/05/2018',
         '10/12/2018',
         '10/19/2018',
         '10/26/2018',
         '11/02/2018',
         '11/09/2018',
         '11/16/2018',
         '11/23/2018',
         '11/30/2018',
         '12/07/2018',
         '12/14/2018',
         '12/21/2018']
    
    def date_range(start, stop, step=1, inclusive=False):
        day_count = (stop - start).days
        if inclusive:
            day_count += 1
    
        if step > 0:
            range_args = (0, day_count, step)
        elif step < 0:
            range_args = (day_count - 1, -1, step)
        else:
            raise ValueError("date_range(): step arg must be non-zero")
    
        for i in range(*range_args):
            yield start + timedelta(days=i)
    
    import datetime
    from dateutil.rrule import DAILY,rrule
    
    date=datetime.datetime(2019,1,10)
    
    date1=datetime.datetime(2019,2,2)
    
    for i in rrule(DAILY , dtstart=date,until=date1):
         print(i.strftime('%Y%b%d'),sep='\n')
    
    2019Jan10
    2019Jan11
    2019Jan12
    2019Jan13
    2019Jan14
    2019Jan15
    2019Jan16
    2019Jan17
    2019Jan18
    2019Jan19
    2019Jan20
    2019Jan21
    2019Jan22
    2019Jan23
    2019Jan24
    2019Jan25
    2019Jan26
    2019Jan27
    2019Jan28
    2019Jan29
    2019Jan30
    2019Jan31
    2019Feb01
    2019Feb02
    
    from datetime import date,timedelta
    delta = timedelta(days=1)
    start = date(2020,1,1)
    end=date(2020,9,1)
    loop_date = start
    while loop_date<=end:
        print(loop_date)
        loop_date+=delta
    
    import pendulum
    
    start = pendulum.from_format('2020-05-01', 'YYYY-MM-DD', formatter='alternative')
    end = pendulum.from_format('2020-05-02', 'YYYY-MM-DD', formatter='alternative')
    
    period = pendulum.period(start, end)
    
    for dt in period:
        print(dt.to_date_string())
    
    from datetime import date, timedelta
    from itertools import count, takewhile
    
    for d in takewhile(lambda x: x<=date(2009,6,9), map(lambda x:date(2009,5,30)+timedelta(days=x), count())):
        print(d)
    
    from arrow import Arrow
    
    >>> start = datetime(2013, 5, 5, 12, 30)
    >>> end = datetime(2013, 5, 5, 17, 15)
    >>> for r in Arrow.range('hour', start, end):
    ...     print repr(r)
    ...
    <Arrow [2013-05-05T12:30:00+00:00]>
    <Arrow [2013-05-05T13:30:00+00:00]>
    <Arrow [2013-05-05T14:30:00+00:00]>
    <Arrow [2013-05-05T15:30:00+00:00]>
    <Arrow [2013-05-05T16:30:00+00:00]>
    
    >>> start = Arrow(2013, 5, 5)
    >>> end = Arrow(2013, 5, 5)
    >>> for r in Arrow.range('day', start, end):
    ...     print repr(r)