Come calcolare il numero di giorni tra due date indicate?


507

Se ho due date (es. '8/18/2008'E '9/26/2008'), qual è il modo migliore per ottenere il numero di giorni tra queste due date?

Risposte:


802

Se hai due oggetti data, puoi semplicemente sottrarli, il che calcola un timedeltaoggetto.

from datetime import date

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

La sezione pertinente della documentazione: https://docs.python.org/library/datetime.html .

Vedi questa risposta per un altro esempio.


2
Grandi risposte qui. Dal momento che un sacco di gente potrebbe essere utilizzando panda frame di dati, il pensiero potrebbe essere utile per verificare il collegamento su come convertire da np.datetime64a python datetime stackoverflow.com/questions/52982056/...
Pramit

La cosa bella è che questa soluzione restituisce delta corretto anche per gli anni bisestili.
Lasma,

154

Usando il potere del 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

4
in realtà, la classe di data sarebbe più appropriata in questo caso rispetto al datetime.
Jeremy Cantrell,

11
@JeremyCantrell Eppure, anche otto anni dopo, datemanca ancora il suo equivalente strptime().
JAB,

Perché ha bisogno strptimel' formatarg? Dovrebbe essere chiaro con la prima data arg che ha un formato.
Timo,

36

Giorni fino a Natale:

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

Più aritmetica qui .


16

Vuoi il modulo datetime.

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

Un altro esempio:

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

Come indicato qui


1
Come ottengo questo senza 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)

2
Ciò non aggiunge nulla di nuovo rispetto alle risposte fornite 4 anni prima. -1.
Mark Amery,

+1 per l'uso di abs(), che è utile quando le date confrontate sono sconosciute in anticipo ed è la differenza che ti interessa. Se la tua seconda data datetime.strptime(date, date)è successiva alla prima, il risultato sarà negativo. abs()rende tutti gli input assoluti (cioè positivi).
Veuncent


6

senza usare Lib solo codice 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()

3

tutti hanno risposto in modo eccellente usando la data, fammi provare a rispondere usando i panda

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

Questo darà la risposta. Nel caso in cui uno degli input sia la colonna dataframe. usa semplicemente dt.days al posto dei giorni

(dt1-dt).dt.days

2

C'è anche un datetime.toordinal()metodo che non è stato ancora menzionato:

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

Restituisce l'ordinale del calendario Gregoriano prolettico della data, dove 1 gennaio dell'anno 1 ha ordinale 1. Per ogni dateoggetto d , date.fromordinal(d.toordinal()) == d.

Sembra adatto per calcolare la differenza di giorni, anche se non è leggibile come timedelta.days.


1
Ci sono casi in cui questo approccio vince. Ad esempio, la differenza effettiva tra il 2019-07-09 23:50 e il 2019-07-10 00:10 è di venti minuti. (d1 - d0).daysritorna 0, d1.toordinal() - d0.toordinal()ritorna 1. Dipende da ciò di cui hai bisogno nel tuo caso reale.
peter.slizik,

questo approccio può effettivamente confrontare data e ora. Ad esempio per verificare se 2020-04-17 == 2020-04017 00:00:00
Harry Duong,

2

Per calcolare date e orari, ci sono diverse opzioni ma scriverò in modo semplice:

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

Spero che sia d'aiuto


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

Ciò presuppone, ovviamente, che tu abbia già verificato che le tue date siano nel formato r'\d+/\d+/\d+'.


1
Ciò non aggiunge nulla di nuovo rispetto alle risposte fornite 8 anni prima. -1.
Mark Amery,

1
La differenza principale è che la maggior parte delle altre risposte non si è nemmeno preoccupata di rendere conto del fatto che il PO aveva le sue date come stringhe. E quelli che spiegavano che in gran parte usavano formattatori più complicati di quanto strettamente necessario. Quindi, la differenza principale è map(int, s.split('/')). Non esattamente rivoluzionario, ma di nuovo questa domanda è piuttosto stupida di base. La mia risposta mostra solo un altro modo di scuoiare il gatto.
Parthian Shot,

Ha anche menzionato la convalida che le date sono nel formato corretto e ha fornito una regex di convalida di prima approssimazione. Quali altri no.
Parthian Shot,

1

Ecco tre modi per affrontare questo 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.