Comment calculer le nombre de jours entre deux dates données?

507

Si j'ai deux dates (ex. '8/18/2008'Et '9/26/2008'), quelle est la meilleure façon d'obtenir le nombre de jours entre ces deux dates?

Rayon
la source

Réponses:

802

Si vous avez deux objets de date, vous pouvez simplement les soustraire, ce qui calcule un timedeltaobjet.

from datetime import date

d0 = date(2008, 8, 18)
d1 = date(2008, 9, 26)
delta = d1 - d0
print(delta.days)

La section pertinente de la documentation: https://docs.python.org/library/datetime.html .

Voir cette réponse pour un autre exemple.

Dana
la source
2
Excellentes réponses ici. Étant donné que beaucoup de gens pourraient utiliser le cadre de données pandas, il pourrait être utile de vérifier le lien sur la façon de convertir de np.datetime64à python datetime stackoverflow.com/questions/52982056/…
Pramit
La bonne chose est que cette solution renvoie également un delta correct pour les années bissextiles.
Lasma
154

Utilisation de la puissance de datetime:

from datetime import datetime
date_format = "%m/%d/%Y"
a = datetime.strptime('8/18/2008', date_format)
b = datetime.strptime('9/26/2008', date_format)
delta = b - a
print delta.days # that's it
dguaraglia
la source
4
en fait, la classe de date serait plus appropriée dans ce cas que datetime.
Jeremy Cantrell
11
@JeremyCantrell Et pourtant, même huit ans plus tard, dateil manque toujours son propre équivalent à strptime().
JAB
Pourquoi a besoin de strptimel' formatargument? Doit être clair avec la première date d'argument qui a un format.
Timo
36

Jours jusqu'à Noël:

>>> import datetime
>>> today = datetime.date.today()
>>> someday = datetime.date(2008, 12, 25)
>>> diff = someday - today
>>> diff.days
86

Plus arithmétique ici .

Harley Holcombe
la source
16

Vous voulez le module datetime.

>>> from datetime import datetime, timedelta 
>>> datetime(2008,08,18) - datetime(2008,09,26) 
datetime.timedelta(4) 

Un autre exemple:

>>> import datetime 
>>> today = datetime.date.today() 
>>> print(today)
2008-09-01 
>>> last_year = datetime.date(2007, 9, 1) 
>>> print(today - last_year)
366 days, 0:00:00 

Comme indiqué ici

kolrie
la source
1
Comment puis-je obtenir cela sans la partie 0:00:00?
Vicki B
@VickiBdelta = today - last_year print(delta.days)
dbakiu
8
from datetime import datetime
start_date = datetime.strptime('8/18/2008', "%m/%d/%Y")
end_date = datetime.strptime('9/26/2008', "%m/%d/%Y")
print abs((end_date-start_date).days)
Prasanna Ranganathan
la source
2
Cela n'ajoute rien de nouveau par rapport aux réponses données 4 ans plus tôt. -1.
Mark Amery
+1 pour l'utilisation de abs(), ce qui est utile lorsque les dates comparées sont inconnues à l'avance et que c'est la différence qui vous intéresse. Si votre deuxième date en datetime.strptime(date, date)est postérieure à la première date, le résultat sera négatif. abs()rend toutes les entrées absolues (c'est-à-dire positives).
veuncent
7

Cela peut également être fait facilement avec arrow:

import arrow

a = arrow.get('2017-05-09')
b = arrow.get('2017-05-11')

delta = (b-a)
print delta.days

Pour référence: http://arrow.readthedocs.io/en/latest/

cimarie
la source
6

sans utiliser du code purement Lib:

#Calculate the Days between Two Date

daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def isLeapYear(year):

    # Pseudo code for this algorithm is found at
    # http://en.wikipedia.org/wiki/Leap_year#Algorithm
    ## if (year is not divisible by 4) then (it is a common Year)
    #else if (year is not divisable by 100) then (ut us a leap year)
    #else if (year is not disible by 400) then (it is a common year)
    #else(it is aleap year)
    return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

def Count_Days(year1, month1, day1):
    if month1 ==2:
        if isLeapYear(year1):
            if day1 < daysOfMonths[month1-1]+1:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
        else: 
            if day1 < daysOfMonths[month1-1]:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
    else:
        if day1 < daysOfMonths[month1-1]:
             return year1, month1, day1+1
        else:
            if month1 ==12:
                return year1+1,1,1
            else:
                    return year1, month1 +1 , 1


def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):

    if y1 > y2:
        m1,m2 = m2,m1
        y1,y2 = y2,y1
        d1,d2 = d2,d1
    days=0
    while(not(m1==m2 and y1==y2 and d1==d2)):
        y1,m1,d1 = Count_Days(y1,m1,d1)
        days+=1
    if end_day:
        days+=1
    return days


# Test Case

def test():
    test_cases = [((2012,1,1,2012,2,28,False), 58), 
                  ((2012,1,1,2012,3,1,False), 60),
                  ((2011,6,30,2012,6,30,False), 366),
                  ((2011,1,1,2012,8,8,False), 585 ),
                  ((1994,5,15,2019,8,31,False), 9239),
                  ((1999,3,24,2018,2,4,False), 6892),
                  ((1999,6,24,2018,8,4,False),6981),
                  ((1995,5,24,2018,12,15,False),8606),
                  ((1994,8,24,2019,12,15,True),9245),
                  ((2019,12,15,1994,8,24,True),9245),
                  ((2019,5,15,1994,10,24,True),8970),
                  ((1994,11,24,2019,8,15,True),9031)]

    for (args, answer) in test_cases:
        result = daysBetweenDates(*args)
        if result != answer:
            print "Test with data:", args, "failed"
        else:
            print "Test case passed!"

test()
Muhammad Elsayeh
la source
3

tout le monde a très bien répondu en utilisant la date, permettez-moi d'essayer d'y répondre en utilisant des pandas

dt = pd.to_datetime('2008/08/18', format='%Y/%m/%d')
dt1 = pd.to_datetime('2008/09/26', format='%Y/%m/%d')

(dt1-dt).days

Cela donnera la réponse. Dans le cas où l'une des entrées est la colonne de trame de données. utilisez simplement dt.days à la place des jours

(dt1-dt).dt.days
Amit Gupta
la source
2

Il existe également une datetime.toordinal()méthode qui n'a pas encore été mentionnée:

import datetime
print(datetime.date(2008,9,26).toordinal() - datetime.date(2008,8,18).toordinal())  # 39

https://docs.python.org/3/library/datetime.html#datetime.date.toordinal

date.toordinal ()

Retour le proleptic ordinale Grégorienne de la date, où 1 Janvier de l' année 1 a 1. Pour tout ordinal dateobjet d , date.fromordinal(d.toordinal()) == d.

Semble bien adapté pour calculer la différence de jours, mais pas aussi lisible que timedelta.days.

Dmitriy Work
la source
1
Il y a des cas où cette approche l'emporte. Par exemple, la différence réelle entre 2019-07-09 23:50 et 2019-07-10 00:10 est de vingt minutes. (d1 - d0).daysrevient 0, d1.toordinal() - d0.toordinal()revient 1. Cela dépend de ce dont vous avez besoin dans votre cas d'utilisation réel.
peter.slizik
cette approche peut réellement comparer datetime et date. Par exemple pour vérifier si 2020-04-17 == 2020-04017 00:00:00
Harry Duong
2

Pour calculer les dates et les heures, il existe plusieurs options mais j'écrirai de la manière la plus simple:

from datetime import timedelta, datetime, date
import dateutil.relativedelta

# current time
date_and_time = datetime.datetime.now()
date_only = date.today()
time_only = datetime.datetime.now().time()

# calculate date and time
result = date_and_time - datetime.timedelta(hours=26, minutes=25, seconds=10)

# calculate dates: years (-/+)
result = date_only - dateutil.relativedelta.relativedelta(years=10)

# months
result = date_only - dateutil.relativedelta.relativedelta(months=10)

# days
result = date_only - dateutil.relativedelta.relativedelta(days=10)

# calculate time 
result = date_and_time - datetime.timedelta(hours=26, minutes=25, seconds=10)
result.time()

J'espère que cela aide

Gavriel Cohen
la source
1

from datetime import date
def d(s):
  [month, day, year] = map(int, s.split('/'))
  return date(year, month, day)
def days(start, end):
  return (d(end) - d(start)).days
print days('8/18/2008', '9/26/2008')

Cela suppose, bien sûr, que vous avez déjà vérifié que vos dates sont au format r'\d+/\d+/\d+'.

Flèche du Parthe
la source
1
Cela n'ajoute rien de nouveau par rapport aux réponses données 8 ans plus tôt. -1.
Mark Amery
1
La principale différence est que la plupart des autres réponses n'ont même pas pris la peine de tenir compte du fait que le PO avait ses dates comme chaînes. Et ceux qui en ont tenu compte ont largement utilisé des formateurs plus complexes que strictement nécessaires. Donc, la principale différence est map(int, s.split('/')). Pas vraiment révolutionnaire, mais là encore, cette question est assez stupide de base. Ma réponse montre juste une autre façon d'écorcher le chat.
Parthian Shot
A également mentionné la validation que les dates sont au format correct et a donné une expression rationnelle de validation de première approximation. Ce que d'autres n'ont pas fait.
Parthian Shot
1

Voici trois façons de résoudre ce problème:

from datetime import datetime

Now = datetime.now()
StartDate = datetime.strptime(str(Now.year) +'-01-01', '%Y-%m-%d')
NumberOfDays = (Now - StartDate)

print(NumberOfDays.days)                     # Starts at 0
print(datetime.now().timetuple().tm_yday)    # Starts at 1
print(Now.strftime('%j'))                    # Starts at 1
Antoine Thiry
la source