web-dev-qa-db-fra.com

Création d'une plage de dates en Python

Je veux créer une liste de dates, commençant aujourd'hui, et remontant d'un nombre arbitraire de jours, disons, dans mon exemple, 100 jours. Y a-t-il une meilleure façon de le faire que cela?

import datetime

a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
    dateList.append(a - datetime.timedelta(days = x))
print dateList
237
Thomas Browne

Un peu mieux ...

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(0, numdays)]
344
S.Lott

Pandas convient parfaitement aux séries chronologiques et prend en charge directement les plages de dates. 

Par exemple, pd.date_range() :

import pandas as pd
datelist = pd.date_range(pd.datetime.today(), periods=100).tolist()

Il a également beaucoup d'options pour vous rendre la vie plus facile. Par exemple, si vous ne voulez que les jours de semaine, vous devez simplement échanger bdate_range .

Voir http://pandas.pydata.org/pandas-docs/stable/timeseries.html#generating-ranges-of-timestamps

De plus, il prend pleinement en charge les fuseaux horaires Pytz et peut s’étendre sans heurts entre les changements DST printemps/automne.

166
fantabolous

Obtenir une plage de dates entre les dates de début et de fin spécifiées (optimisées pour la complexité spatio-temporelle):

import datetime

start = datetime.datetime.strptime("21-06-2014", "%d-%m-%Y")
end = datetime.datetime.strptime("07-07-2014", "%d-%m-%Y")
date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

for date in date_generated:
    print date.strftime("%d-%m-%Y")
48
Sandeep

Vous pouvez écrire une fonction génératrice qui renvoie des objets de date à partir d’aujourd’hui:

import datetime

def date_generator():
  from_date = datetime.datetime.today()
  while True:
    yield from_date
    from_date = from_date - datetime.timedelta(days=1)

Ce générateur renvoie les dates à partir d’aujourd’hui et recule d’un jour à l’autre. Voici comment prendre les 3 premières dates:

>>> import itertools
>>> dates = itertools.islice(date_generator(), 3)
>>> list(dates)
[datetime.datetime(2009, 6, 14, 19, 12, 21, 703890), datetime.datetime(2009, 6, 13, 19, 12, 21, 703890), datetime.datetime(2009, 6, 12, 19, 12, 21, 703890)]

L'avantage de cette approche par rapport à une lecture en boucle ou en liste est que vous pouvez revenir autant de fois que vous le souhaitez.

Modifier

Une version plus compacte utilisant une expression génératrice à la place d'une fonction:

date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())

Usage:

>>> dates = itertools.islice(date_generator, 3)
>>> list(dates)
[datetime.datetime(2009, 6, 15, 1, 32, 37, 286765), datetime.datetime(2009, 6, 14, 1, 32, 37, 286836), datetime.datetime(2009, 6, 13, 1, 32, 37, 286859)]
40
Ayman Hourieh

Vous pouvez également utiliser l'ordinal du jour pour simplifier les choses:

def date_range(start_date, end_date):
    for ordinal in range(start_date.toordinal(), end_date.toordinal()):
        yield datetime.date.fromordinal(ordinal)

Ou, comme suggéré dans les commentaires, vous pouvez créer une liste comme celle-ci:

date_range = [
    datetime.date.fromordinal(ordinal) 
    for ordinal in range(
        start_date.toordinal(),
        end_date.toordinal(),
    )
]
31
Hosane

oui, réinventer la roue ...... il suffit de rechercher le forum et vous obtiendrez quelque chose comme ceci: 

from dateutil import rrule
from datetime import datetime

list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))
29
BOFH

D'après le titre de cette question, je m'attendais à trouver quelque chose comme range(), qui me permettrait de spécifier deux dates et de créer une liste avec toutes les dates entre les deux. De cette façon, il n'est pas nécessaire de calculer le nombre de jours entre ces deux dates, si on ne le sait pas à l'avance.

Donc, avec le risque d'être légèrement hors sujet, ce one-line fait le travail:

import datetime
start_date = datetime.date(2011, 01, 01)
end_date   = datetime.date(2014, 01, 01)

dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]

Tous les crédits à cette réponse

15
snake_charmer

Je connais un peu votre réponse, mais je viens d'avoir le même problème et j'ai décidé que la fonction d'intervalle interne de Python manquait un peu à cet égard; je l'ai donc remplacée dans un de mes modules util.

from __builtin__ import range as _range
from datetime import datetime, timedelta

def range(*args):
    if len(args) != 3:
        return _range(*args)
    start, stop, step = args
    if start < stop:
        cmp = lambda a, b: a < b
        inc = lambda a: a + step
    else:
        cmp = lambda a, b: a > b
        inc = lambda a: a - step
    output = [start]
    while cmp(start, stop):
        start = inc(start)
        output.append(start)

    return output

print range(datetime(2011, 5, 1), datetime(2011, 10, 1), timedelta(days=30))
7
Rob Young

Voici Gist que j'ai créé, à partir de mon propre code, cela pourrait aider. (Je sais que la question est trop ancienne, mais d'autres peuvent l'utiliser.)

https://Gist.github.com/2287345

(même chose ci-dessous)

import datetime
from time import mktime

def convert_date_to_datetime(date_object):
    date_Tuple = date_object.timetuple()
    date_timestamp = mktime(date_Tuple)
    return datetime.datetime.fromtimestamp(date_timestamp)

def date_range(how_many=7):
    for x in range(0, how_many):
        some_date = datetime.datetime.today() - datetime.timedelta(days=x)
        some_datetime = convert_date_to_datetime(some_date.date())
        yield some_datetime

def pick_two_dates(how_many=7):
    a = b = convert_date_to_datetime(datetime.datetime.now().date())
    for each_date in date_range(how_many):
        b = a
        a = each_date
        if a == b:
            continue
        yield b, a
5
roopesh

Voici une ligne pour que les scripts bash obtiennent une liste des jours de la semaine. Il s’agit de python 3. Facilement modifié, peu importe l’int, le int à la fin est le nombre de jours que vous souhaitez. 

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.today() - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int(sys.argv[1])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 10

Voici une variante pour fournir une date de début (ou plutôt de fin)

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d \") for x in range(0,int(sys.argv[2])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/30 10

Voici une variante pour des dates de début et de fin arbitraires. pas que ce soit pas très efficace, mais c'est bien pour mettre dans une boucle for dans un script bash:

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") + datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int((datetime.datetime.strptime(sys.argv[2], \"%Y/%m/%d\") - datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\")).days)) if (datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\") + datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/15 2015/12/30
4
Tim P

Voici une réponse légèrement différente de la réponse de S.Lott, qui donne une liste des dates entre deux dates start et end. Dans l'exemple ci-dessous, du début de 2017 à aujourd'hui.

start = datetime.datetime(2017,1,1)
end = datetime.datetime.today()
daterange = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
4
Derek Powell

Lié à Matplotlib

from matplotlib.dates import drange
import datetime

base = datetime.date.today()
end  = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
l = drange(base, end, delta)
3
milton

S'il y a deux dates et que vous avez besoin de la plage, essayez 

from dateutil import rrule, parser
date1 = '1995-01-01'
date2 = '1995-02-28'
datesx = list(rrule.rrule(rrule.DAILY, dtstart=parser.parse(date1), until=parser.parse(date2)))
3
Nelu

Je sais que la réponse à cette question a été trouvée, mais je vais la poser pour des raisons historiques et, à mon avis, elle est simple.

import numpy as np
import datetime as dt
listOfDates=[date for date in np.arange(firstDate,lastDate,dt.timedelta(days=x))]

Bien sûr, il ne gagnera rien comme le code-golf, mais je pense que c'est élégant.

2

Sur la base des réponses que j'ai écrites moi-même ceci:

import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]

Sortie:

['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']

La différence est que je reçois l'objet 'date', pas celui 'datetime.datetime'.

2
wmlynarski
from datetime import datetime, timedelta
from dateutil import parser
def getDateRange(begin, end):
    """  """
    beginDate = parser.parse(begin)
    endDate =  parser.parse(end)
    delta = endDate-beginDate
    numdays = delta.days + 1
    dayList = [datetime.strftime(beginDate + timedelta(days=x), '%Y%m%d') for x in range(0, numdays)]
    return dayList
1
xmduhan

Un générateur de plage de dates mensuel avec datetime et dateutil. Simple et facile à comprendre:

import datetime as dt
from dateutil.relativedelta import relativedelta

def month_range(start_date, n_months):
        for m in range(n_months):
            yield start_date + relativedelta(months=+m)
1
aysa
import datetime    
def date_generator():
    cur = base = datetime.date.today()
    end  = base + datetime.timedelta(days=100)
    delta = datetime.timedelta(days=1)
    while(end>base):
        base = base+delta
        print base

date_generator()
0
Sasmita