Corso
Molti dataset del mondo reale includono date e orari, e un'operazione comune nella data science è calcolare la differenza temporale tra due istanti.
Le unità che usiamo per misurare date e orari (anni, mesi, giorni, ore, minuti, secondi) non sono le più semplici con cui lavorare, soprattutto quando hanno durate irregolari.
Tuttavia, il tipo di dato timedelta di Python, che fa parte del modulo datetime, gestisce le complessità del calcolo degli intervalli di tempo.
Cominciamo con una risposta molto breve su cos'è timedelta in Python e poi proseguiamo con maggiori dettagli.
Per saperne di più su date e orari in Python, dai un'occhiata a questo corso su Working With Dates and Time in Python.
Risposta breve: cos'è timedelta in Python
I due tipi di dato più importanti e utilizzati del modulo datetime sono timedelta e datetime. Mentre gli oggetti datetime rappresentano istanti specifici nel tempo (ad esempio, 1 gennaio 2024 alle 10:30), gli oggetti timedelta rappresentano durate o intervalli tra due punti. Pensalo come la differenza tra chiedere "Quando?" (datetime) e "Per quanto?" (timedelta).
Considera due date, che possiamo rappresentare usando due oggetti datetime. Sottraendo una data dall'altra si crea un oggetto timedelta che rappresenta l'intervallo tra le due date:
import datetime
first_date = datetime.datetime(year=2024, month=1, day=1)
second_date = datetime.datetime(year=2024, month=5, day=27)
interval = second_date - first_date
print(interval)
147 days, 0:00:00
L'output mostra che le due date distano esattamente 147 giorni. Nel seguente esempio, usiamo la data e l'ora di esecuzione del codice chiamando datetime.datetime.now():
first_date = datetime.datetime(year=2024, month=1, day=1)
second_date = datetime.datetime.now()
interval = second_date - first_date
print(second_date)
print(interval)
2024-05-28 08:32:44.871646
148 days, 8:32:44.871646
L'oggetto timedelta ora mostra il tempo trascorso dall'inizio del 2024 alla data e ora di esecuzione del codice.
Approfondiremo ulteriormente timedelta di Python in questo articolo.
Creare oggetti timedelta
Nella sezione precedente abbiamo creato un oggetto timedelta a partire da due oggetti datetime, ma possiamo anche creare direttamente un intervallo di tempo chiamando il costruttore timedelta():
interval = datetime.timedelta(days=10, seconds=3600)
print(interval)
10 days, 1:00:00
L'intervallo dura dieci giorni e un'ora. Possiamo anche usare altre unità di tempo quando creiamo un'istanza di timedelta:
interval = datetime.timedelta(weeks=1, days=3, hours=1)
print(interval)
10 days, 1:00:00
Qualsiasi delle seguenti unità di tempo è valida quando si chiama timedelta():
- weeks
- days
- hours
- minutes
- seconds
- milliseconds
- microseconds
Questo tutorial approfondirà come gli intervalli di tempo sono memorizzati in un oggetto timedelta.
Aritmetica di base con timedelta
Possiamo anche eseguire operazioni aritmetiche con gli oggetti timedelta. Considera i seguenti tre oggetti datetime, che rappresentano le date di rilascio di Python 1.0, Python 2.0 e Python 3.0. Sottrarre oggetti datetime tra loro crea un oggetto timedelta:
release_date_python_1 = datetime.datetime(year=1991, month=2, day=20)
release_date_python_2 = datetime.datetime(year=2000, month=10, day=16)
release_date_python_3 = datetime.datetime(year=2008, month=12, day=3)
time_between_1_and_2 = release_date_python_2 - release_date_python_1
time_between_2_and_3 = release_date_python_3 - release_date_python_2
print(time_between_1_and_2)
print(time_between_2_and_3)
3526 days, 0:00:00
2970 days, 0:00:00
L'output mostra il numero di giorni tra i rilasci di Python 1.0 e 2.0 e tra i rilasci di Python 2.0 e 3.0. Gli intervalli di tempo sono oggetti timedelta.
È anche possibile effettuare addizioni e sottrazioni tra oggetti timedelta e oggetti datetime. Aggiungiamo un timedelta con days=100 a release_date_python_3:
print(release_date_python_3 + datetime.timedelta(days=100))
2009-03-13 00:00:00
Python 3.0 è stato rilasciato il 3 dicembre 2008. Aggiungere cento giorni a questa data ci porta al 13 marzo 2009.
Possiamo però eseguire operazioni aritmetiche direttamente anche con oggetti timedelta:
print("Difference between gap 1 and gap 2")
print(time_between_1_and_2 - time_between_2_and_3)
print("Sum of gap 1 and gap 2")
print(time_between_1_and_2 + time_between_2_and_3)
Difference between gap 1 and gap 2
556 days, 0:00:00
Sum of gap 1 and gap 2
6496 days, 0:00:00
L'output conferma che è possibile sottrarre e sommare oggetti timedelta. Anche moltiplicazione e divisione sono possibili:
print("Multiply time interval by 3:")
print(time_between_1_and_2 * 3)
print("Divide time interval by 3:")
print(time_between_1_and_2 / 3)
Multiply time interval by 3:
10578 days, 0:00:00
Divide time interval by 3:
1175 days, 8:00:00
Possiamo anche confrontare oggetti timedelta:
print("Check if gap 1 is greater than gap 2")
print(time_between_1_and_2 > time_between_2_and_3)
True
L'output conferma che l'intervallo tra le date di rilascio di Python 1.0 e Python 2.0 è più lungo dell'intervallo tra Python 2.0 e Python 3.0.
Principali attributi e metodi di timedelta
Un oggetto timedelta rappresenta un intervallo di tempo memorizzando il numero di giorni, secondi e microsecondi. Queste tre unità sono le uniche rappresentate come attributi nella classe timedelta:
interval = datetime.timedelta(
weeks=1,
hours=10,
minutes=22,
milliseconds=1042,
)
print(f"{interval = }")
print(f"{interval.days = }")
print(f"{interval.seconds = }")
print(f"{interval.microseconds = }")
interval = datetime.timedelta(days=7, seconds=37321, microseconds=42000)
interval.days = 7
interval.seconds = 37321
interval.microseconds = 42000
Anche se la chiamata a timedelta() include argomenti per settimane, ore, minuti e millisecondi, il costruttore converte queste unità in giorni, secondi e microsecondi. Le chiamate a print() includono f-string con un segno di uguale = per mostrare il nome della variabile e il suo valore. Puoi saperne di più sulle f-string in questo tutorial su la formattazione con f-string in Python.
Un altro strumento utile della classe timedelta è il metodo total_seconds(). Questo metodo restituisce l'intero intervallo di tempo in secondi:
print("Total time interval in seconds:")
print(interval.total_seconds())
Total time interval in seconds:
642121.042
Questo valore rappresenta l'intero intervallo in secondi. Non è lo stesso del valore di .seconds, che mostra solo la componente in secondi dell'intervallo senza tenere conto di giorni e microsecondi.
Possiamo usare il valore restituito da .total_seconds() per convertire l'intervallo in qualsiasi altra unità:
print("Total time interval in days:")
print(interval.total_seconds() / 3600 / 24)
Total time interval in days:
7.431956504629629
L'output mostra l'intervallo in giorni, poiché il valore restituito da .total_seconds() è diviso per il numero di secondi in un'ora e per il numero di ore in un giorno.
Esempio con timedelta: calcolare la crescita
Vediamo un esempio. Il negozio online di un'azienda che vende libri su Python registra tutte le vendite. Ecco i dati per un cliente:
data = {
"customer_id": 3542,
"sales": [
{"date": "2024-04-21T13:23:45", "price": 24.99, "quantity": 1},
{"date": "2024-02-13T10:54:12", "price": 24.99, "quantity": 2},
{"date": "2024-01-08T20:32:24", "price": 18.99, "quantity": 1},
],
}
Dobbiamo calcolare la differenza di tempo tra il primo e l'ultimo ordine di un cliente. Gli ordini sono sempre in ordine cronologico nell'elenco che contiene tutte le vendite.
Il primo passo è estrarre le date da questa struttura annidata e convertirle in oggetti datetime. Fortunatamente, i timestamp sono nel formato standard ISO 8601 (YYYY-MM-DDTHH:MM:SS), quindi possiamo usare il comodo metodo fromisoformat():
sales = data["sales"]
dates = []
for item in sales:
date = datetime.datetime.fromisoformat(item["date"])
dates.append(date)
print(dates)
[datetime.datetime(2024, 4, 21, 13, 23, 45), datetime.datetime(2024, 2, 13, 10, 54, 12), datetime.datetime(2024, 1, 8, 20, 32, 24)]
La lista dates contiene oggetti datetime con le date di ciascun ordine. Infine, possiamo calcolare l'intervallo tra il primo e l'ultimo ordine:
time_span = dates[0] - dates[-1]
print(time_span)
print(time_span.days)
103 days, 16:51:21
103
La differenza tra la prima e l'ultima data restituisce un oggetto timedelta. Il codice mostra time_span, che riporta numero di giorni, ore, minuti e secondi. Mostriamo anche time_span.days per visualizzare solo il numero intero di giorni.
Se vuoi saperne di più sulla conversione delle stringhe in datetime, consulta questo tutorial su Python String to Datetime.
Consigli rapidi quando usi timedelta
Vediamo alcune cose da tenere a mente quando usi timedelta di Python:
1. È meglio usare argomenti con parola chiave quando chiami timedelta() per evitare errori con le unità:
interval = datetime.timedelta(weeks=1, days=3, hours=1, milliseconds=1354)
2. Quando trovi un intervallo tra due date in fusi orari diversi, timedelta converte le date in UTC prima di calcolare la differenza:
import zoneinfo
some_date = datetime.datetime.fromisoformat("2024-01-01T00:00:00")
some_date_lon = some_date.replace(tzinfo=zoneinfo.ZoneInfo("Europe/London"))
some_date_nyc = some_date.replace(tzinfo=zoneinfo.ZoneInfo("America/New_York"))
print(some_date_lon)
print(some_date_nyc)
print(some_date_nyc - some_date_lon)
2024-01-01 00:00:00+00:00
2024-01-01 00:00:00-05:00
5:00:00
La data in some_date indica l'inizio del nuovo anno. Questo è un oggetto datetime naive, dato che non ha informazioni sul fuso orario. Tuttavia, some_date_lon e some_date_nyc sono oggetti datetime aware, poiché rappresentano l'inizio del nuovo anno rispettivamente a Londra e a New York.
Il timedelta ottenuto sottraendo i due oggetti datetime aware mostra un intervallo di cinque ore, che è la differenza oraria rispetto all'UTC.
3. Le modifiche dell'ora legale non sono prese in considerazione da timedelta:
nyc = zoneinfo.ZoneInfo("America/New_York")
first_time = datetime.datetime.strptime("2024-03-10 1:00am", "%Y-%m-%d %I:%M%p")
first_time = first_time.replace(tzinfo=nyc)
second_time = datetime.datetime.strptime("2024-03-10 3:00am", "%Y-%m-%d %I:%M%p")
second_time = second_time.replace(tzinfo=nyc)
time_difference = second_time - first_time
print("Time difference between the first and second time:")
print(time_difference)
print("Checking the DST status of the first and second time:")
print(f"{first_time.dst() = }")
print(f"{second_time.dst() = }")
Time difference between the first and second time:
2:00:00
Checking the DST status of the first and second time:
first_time.dst() = datetime.timedelta(0)
second_time.dst() = datetime.timedelta(seconds=3600)
I due orari rappresentano l'1:00 e le 3:00 del 3 marzo 2024 a New York. L'ora legale è iniziata alle 2:00 dello stesso giorno, quando gli orologi sono passati alle 3:00. La differenza tra i due orari dà un timedelta di due ore, anche se tra i due orari è passata solo un'ora a causa dell'inizio dell'ora legale.
Possiamo convertire in UTC se ci serve il tempo effettivamente trascorso:
first_time_utc = first_time.astimezone(zoneinfo.ZoneInfo("UTC"))
second_time_utc = second_time.astimezone(zoneinfo.ZoneInfo("UTC"))
time_difference_utc = second_time_utc - first_time_utc
print("Actual time difference between the first and second time:")
print(time_difference_utc)
Actual time difference between the first and second time:
1:00:00
Convertire in UTC prima di sottrarre gli oggetti datetime restituisce il tempo effettivo tra i due oggetti datetime.
Conclusione
La classe timedelta di Python offre metodi semplici per gestire gli intervalli di tempo, rendendo più facile lavorare con periodi espressi in varie unità. Abbiamo visto come creare oggetti timedelta ed eseguire operazioni aritmetiche su di essi, tra cui addizione, sottrazione, moltiplicazione e divisione.
Puoi leggere di più sulla gestione di date e orari nei seguenti articoli:
Ho studiato Fisica e Matematica a livello UG presso l’Università di Malta. Poi mi sono trasferito a Londra e ho conseguito il dottorato in Fisica all’Imperial College. Ho lavorato su nuove tecniche ottiche per immagini della retina umana. Ora mi concentro sullo scrivere di Python, comunicare su Python e insegnare Python.


