¿Cómo calcular el número de días entre dos fechas dadas?

507

Si tengo dos fechas (ej. '8/18/2008'Y '9/26/2008'), ¿cuál es la mejor manera de obtener el número de días entre estas dos fechas?

Rayo
fuente

Respuestas:

802

Si tiene dos objetos de fecha, simplemente puede restarlos, lo que calcula un timedeltaobjeto.

from datetime import date

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

La sección relevante de los documentos: https://docs.python.org/library/datetime.html .

Vea esta respuesta para otro ejemplo.

Dana
fuente
2
Grandes respuestas aquí. Dado que muchas personas podrían estar usando el marco de datos de pandas, podría ser útil consultar el enlace sobre cómo convertir np.datetime64a python datetime stackoverflow.com/questions/52982056/…
envía
Lo bueno es que esta solución también devuelve el delta correcto para los años bisiestos.
Lasma
154

Usando el poder 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
fuente
44
en realidad, la clase de fecha sería más apropiada en este caso que datetime.
Jeremy Cantrell
11
@JeremyCantrell Y, sin embargo, incluso ocho años después, datetodavía carece de su propio equivalente strptime().
JAB
¿Por qué necesita strptimeel formatargumento? Debe quedar claro con la primera fecha arg que tiene un formato.
Timo
36

Días hasta Navidad:

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

Más aritmética aquí .

Harley Holcombe
fuente
16

Desea el módulo de fecha y hora.

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

Otro ejemplo:

>>> 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 

Como se señaló aquí

kolrie
fuente
1
¿Cómo consigo esto sin la parte 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
fuente
2
Esto no agrega nada nuevo en comparación con las respuestas dadas 4 años antes. -1.
Mark Amery
+1 para el uso de abs(), que es útil cuando las fechas comparadas son desconocidas de antemano y es la diferencia que le interesa. Si su segunda fecha datetime.strptime(date, date)es posterior a la primera, el resultado será negativo. abs()hace que todas las entradas sean absolutas (es decir, positivas).
veuncent
7

También se puede hacer fácilmente con arrow:

import arrow

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

delta = (b-a)
print delta.days

Para referencia: http://arrow.readthedocs.io/en/latest/

cimarie
fuente
6

sin usar Lib solo código puro:

#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
fuente
3

todos respondieron excelentemente usando la fecha, déjenme intentar responderla usando 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

Esto le dará la respuesta. En caso de que una de las entradas sea la columna del marco de datos. simplemente use dt.days en lugar de días

(dt1-dt).dt.days
Amit Gupta
fuente
2

También hay un datetime.toordinal()método que aún no se mencionó:

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 ()

Devuelva el ordinal gregoriano proleptico de la fecha, donde el 1 de enero del año 1 tiene el ordinal 1. Para cualquier dateobjeto d , date.fromordinal(d.toordinal()) == d .

Parece muy adecuado para calcular la diferencia de días, aunque no tan legible como timedelta.days.

Dmitriy Work
fuente
1
Hay casos en los que este enfoque gana. Por ejemplo, la diferencia real entre 2019-07-09 23:50 y 2019-07-10 00:10 es veinte minutos. (d1 - d0).daysvuelve 0, d1.toordinal() - d0.toordinal()vuelve 1. Depende de lo que necesite en su caso de uso real.
peter.slizik
Este enfoque en realidad puede comparar datetime y date. Por ejemplo, para verificar si 2020-04-17 == 2020-04017 00:00:00
Harry Duong
2

Para calcular fechas y horas, hay varias opciones, pero escribiré de manera 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()

Espero eso ayude

Gavriel Cohen
fuente
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')

Esto supone, por supuesto, que ya ha verificado que sus fechas están en el formato r'\d+/\d+/\d+'.

Tiro de Partia
fuente
1
Esto no agrega nada nuevo en comparación con las respuestas dadas 8 años antes. -1.
Mark Amery
1
La principal diferencia es que la mayoría de las otras respuestas ni siquiera se molestaron en tener en cuenta el hecho de que el OP tenía sus fechas como cadenas. Y aquellos que lo explicaron usaron formateadores más complicados de lo estrictamente necesario. Entonces, la principal diferencia es map(int, s.split('/')). No es exactamente innovador, pero nuevamente esta pregunta es bastante estúpida. Mi respuesta solo muestra otra forma de desollar al gato.
Parthian Shot
También mencionó la validación de que las fechas están en el formato correcto, y dio una expresión regular de validación de primera aproximación. Lo que otros no hicieron.
Parthian Shot
1

Aquí hay tres formas de solucionar este problema:

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
fuente