452 votes

Itération dans une plage de dates en Python

J'ai le code suivant pour le faire, mais comment puis-je l'améliorer ? Pour l'instant, je pense que c'est mieux que des boucles imbriquées, mais ça commence à devenir Perl-one-linerish quand on a un générateur dans une compréhension de liste.

day_count = (end_date - start_date).days + 1
for single_date in [d for d in (start_date + timedelta(n) for n in range(day_count)) if d <= end_date]:
    print strftime("%Y-%m-%d", single_date.timetuple())

Notes

  • Je ne l'utilise pas vraiment pour imprimer. C'est juste pour la démonstration.
  • El start_date y end_date Les variables sont datetime.date car je n'ai pas besoin de l'horodatage. (Ils vont être utilisés pour générer un rapport).

Exemple de sortie

Pour une date de début de 2009-05-30 et une date de fin de validité de 2009-06-09 :

2009-05-30
2009-05-31
2009-06-01
2009-06-02
2009-06-03
2009-06-04
2009-06-05
2009-06-06
2009-06-07
2009-06-08
2009-06-09

3 votes

Juste pour préciser : Je ne pense pas qu'il y ait de différence entre 'time.strftime("%Y-%m-%d", single_date.timetuple())' et le plus court 'single_date.strftime("%Y-%m-%d")'. La plupart des réponses semblent copier le style le plus long.

11 votes

Wow, ces réponses sont beaucoup trop compliquées. Essaie ça : stackoverflow.com/questions/7274267/

0 votes

@GringoSuave : qu'est-ce qui est compliqué dans La réponse de Sean Cavanagh ?

6voto

John Machin Points 39706
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))

4voto

user368996 Points 21
for i in range(16):
    print datetime.date.today() + datetime.timedelta(days=i)

3voto

juanmhidalgo Points 895

J'ai un problème similaire, mais j'ai besoin d'itérer mensuellement au lieu de quotidiennement.

Voici ma solution

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

Exemple n° 1

date_start = datetime(2016, 6, 1)
date_end = datetime(2017, 1, 1)

for p in monthly_range(date_start, date_end):
    print(p)

Sortie

2016-06-01
2016-07-01
2016-08-01
2016-09-01
2016-10-01
2016-11-01
2016-12-01
2017-01-01

Exemple n° 2

date_start = datetime(2017, 1, 1)
date_end = datetime(2016, 6, 1)

for p in monthly_range(date_start, date_end):
    print(p)

Sortie

2017-01-01
2016-12-01
2016-11-01
2016-10-01
2016-09-01
2016-08-01
2016-07-01
2016-06-01

3voto

Shinto Joseph Points 766

Vous pouvez générer une série de dates entre deux dates en utilisant la bibliothèque pandas de manière simple et fiable

import pandas as pd

print pd.date_range(start='1/1/2010', end='1/08/2018', freq='M')

Vous pouvez modifier la fréquence de génération des dates en définissant freq comme D, M, Q, Y (quotidien, mensuel, trimestriel, annuel )

2voto

LetzerWille Points 3393
> 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']

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X