2011-08-10 18 views
28

Duplicar posibles:
Best way to find the months between two dates (in python)Python: Diferencia de 2 datetimes en meses

me gustaría saber cómo puedo tener el número exacto de meses de esta diferencia:

date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S') 
date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d') 

date2-date1 resultados en

datetime.timedelta(183, 43200) 

Me gustaría saber el número exacto de meses, en este caso se debe devolver y no 6 (a causa de la hora)

+0

Esta pregunta ya fue contestada aquí: http://stackoverflow.com/questions/4039879/mejor-forma-de-encontrar-los-meses-entre-dos-fechas-en-python – Dan

+0

no para fecha y hora –

+1

Esto será más fácil de responder una vez que decida qué significa "la cantidad exacta de meses". Un mes no es una duración de duración fija; puede variar de 28 a 31 días. El 1 de enero y el 1 de febrero están más separados que el 1 de febrero y el 1 de marzo; ¿Llamas a ambos intervalos "exactamente 1 mes"? –

Respuesta

22

Usando calendar módulo para averiguar cuántos días tiene cada mes, sólo tiene que contar los meses.

from calendar import monthrange 
from datetime import datetime, timedelta 

def monthdelta(d1, d2): 
    delta = 0 
    while True: 
     mdays = monthrange(d1.year, d1.month)[1] 
     d1 += timedelta(days=mdays) 
     if d1 <= d2: 
      delta += 1 
     else: 
      break 
    return delta 
5

La ventaja de hacerlo de esta manera es que hay pocos dependencias de módulos y sin bucle: los meses se pueden encontrar mediante cálculo directo.

import datetime as dt 

def months_between(date1,date2): 
    if date1>date2: 
     date1,date2=date2,date1 
    m1=date1.year*12+date1.month 
    m2=date2.year*12+date2.month 
    months=m2-m1 
    if date1.day>date2.day: 
     months-=1 
    elif date1.day==date2.day: 
     seconds1=date1.hour*3600+date1.minute+date1.second 
     seconds2=date2.hour*3600+date2.minute+date2.second 
     if seconds1>seconds2: 
      months-=1 
    return months 

date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S') 
date2 = dt.datetime.strptime('2012-02-15', '%Y-%m-%d') 
print(months_between(date1,date2)) 
# 5 

date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S') 
date2 = dt.datetime.strptime('2012-02-15 11:59:00', '%Y-%m-%d %X') 
print(months_between(date1,date2)) 
# 5 

date2 = dt.datetime.strptime('2012-02-15 12:00:00', '%Y-%m-%d %X') 
print(months_between(date1,date2)) 
# 6 

date2 = dt.datetime.strptime('2012-02-15 12:00:01', '%Y-%m-%d %X') 
print(months_between(date1,date2)) 
# 6 
52

Puede usar python-dateutil.

In [4]: from datetime import datetime 

In [5]: date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S') 

In [6]: date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d') 

In [7]: from dateutil import relativedelta 

In [8]: r = relativedelta.relativedelta(date1, date2) 

In [9]: r 
Out[9]: relativedelta(months=-5, days=-30, hours=-12) 
+5

though: 'relativedelta.relativedelta (date (2015, 9, 30), date (2015, 10, 1)). Month' cede 0 que es correcto pero puede no reflejar el resultado esperado si desea saber que los meses son diferente – ezdazuzena

13

Sólo se conocen los requisitos que debe cumplir, pero el hecho de que hay 183 días y 43200 segundos SI entre estas dos fechas destaca una subjetividad inherente a la determinación de la cantidad de meses que "realmente" es.

¿Es un mes de 30 días, o (365/12) días, o ((365 * 4 + 1)/48) días, o ...?

¿Es un día siempre 86400 segundos, o cuenta segundos intercalares históricos, o pronostica segundos intercalares para fechas futuras?

Estas decisiones afectan la respuesta que el algoritmo que parezca desear le dará para ciertas fechas de entrada que están cerca de estos límites.

En mi opinión, es más intuitivo para considerar meses como unidades atómicas de tiempo para este propósito y utilizar esta fórmula: (date2.year - date1.year) * 12 + (date2.month - date1.month)

+0

Esto es eficiente y bien explicado, funcionó para mi problema. –