Corso
Lavorare con date e orari sembra semplice finché non inizi a occuparti di formati, fusi orari, regole dell’ora legale o timestamp provenienti da sistemi diversi: a quel punto non è più un’opzione salvare l’ora come semplici stringhe o interi. Il modulo datetime di Python esiste proprio per aiutarti a gestire tutte queste variabili in modo prevedibile.
Questa guida illustra le classi principali, come creare e usare gli oggetti datetime, come eseguire operazioni aritmetiche, formattare e analizzare i valori, gestire i fusi orari e altro ancora. Ogni sezione si basa sulla precedente, così puoi passare dalle operazioni di base a schemi più avanzati.
Classi principali del modulo datetime di Python
Prima di fare qualcosa di specifico, è utile capire come Python modella date e orari a livello concettuale. Il modulo datetime utilizza un piccolo set di classi, ognuna focalizzata su una parte del problema. Sapere dove si colloca ciascuna classe rende il resto del flusso di lavoro molto più semplice.
date
Quando ti serve solo una data di calendario senza preoccuparti dell’ora del giorno o dei fusi orari, la classe date è quello che ti serve. Rappresenta anno, mese e giorno tramite attributi familiari.
Ecco gli attributi:
-
year -
month -
day
E i metodi:
-
today() -
fromisoformat() -
replace() -
isoformat() -
weekday() -
isoweekday()
from datetime import date
d = date(2025, 3, 1)
print(d)
Questo codice crea una semplice data di calendario. Se inserisci una combinazione non valida (come February 30), Python genera un ValueError.
time
Alcuni compiti riguardano solo l’ora del giorno, ad esempio un promemoria che scatta alle 14:30. La classe time è utile perché memorizza ore, minuti, secondi e, se serve (non in questo esempio), microsecondi o informazioni sul fuso orario.
Gli attributi sono: hour, minute, second, microsecond, tzinfo
I metodi sono: replace(), isoformat()
from datetime import time
t = time(14, 30, 15)
print(t)
Questo crea un orario senza una data associata. Valori non validi (come hour=27) genereranno un errore.
datetime
La maggior parte dei casi reali combina sia data sia ora, ed è qui che entra in gioco datetime. È la classe più versatile del modulo e quella che userai più spesso per registrazione, elaborazione e coordinamento degli eventi.
Gli attributi sono (in aggiunta a tutti quelli sopra): tzinfo
E i metodi sono now(), utcnow(), fromisoformat(), strptime(), strftime(), astimezone(). Supporta anche l’aritmetica con timedelta, che tratterò più nel dettaglio.
from datetime import datetime
dt = datetime(2025, 3, 1, 14, 30)
print(dt)
Questo produce un timestamp completo con componenti di data e ora.
timedelta
Ogni volta che devi misurare il tempo trascorso o spostare un timestamp avanti o indietro, timedelta è la scelta giusta. Rappresenta una durata, non un momento specifico.
Gli attributi sono: days, seconds, microseconds. È comunemente usato per offset, differenze temporali e logiche di scheduling.
from datetime import timedelta
delta = timedelta(days=7, hours=3)
print(delta)
Questo rappresenta una durata a lunghezza fissa. Diventa particolarmente utile quando viene aggiunta o sottratta a un datetime.
tzinfo
tzinfo definisce l’interfaccia di Python per i fusi orari. Non li creerai direttamente, ma il sistema datetime li usa ogni volta che associ o converti fusi orari.
timezone
timezone è un’implementazione tzinfo integrata per offset UTC fissi come UTC o UTC+1. È utile per casi semplici in cui le regole dell’ora legale non contano.
Creare e accedere agli oggetti datetime di Python
Una volta note le classi, il passo successivo è imparare a crearne le istanze. Python offre diversi approcci a seconda dell’origine dei dati: inserimento manuale, orario di sistema, timestamp o testo.
Uso dei costruttori di classe
I costruttori ti danno il pieno controllo sui valori che stai creando. Spesso è il modo più esplicito e resistente agli errori per costruire oggetti date, time o datetime.
from datetime import date
d = date(2025, 3, 1)
print(d)
Questo costruisce direttamente una data di calendario. Valori non validi generano subito un errore, aiutando a intercettare gli errori in anticipo.
from datetime import time
t = time(14, 30, 15)
print(t)
Questo produce un valore di ora del giorno. Usalo quando non ti serve la data associata.
from datetime import datetime
dt = datetime(2025, 3, 1, 14, 30)
print(dt)
Questo crea un timestamp completo. Aggiungere un argomento tzinfo lo rende consapevole del fuso orario.
Creazione da timestamp
I timestamp Unix compaiono in log, API e sistemi operativi. Python li converte facilmente in oggetti datetime leggibili.
datetime.fromtimestamp(1700000000)
datetime.utcfromtimestamp(1700000000)
Il primo interpreta il timestamp nell’ora locale; il secondo lo interpreta in UTC.
Metodi di classe per i valori correnti
Quando ti serve la data o l’ora correnti, Python fornisce comode scorciatoie. Sono essenziali per logging, tracciamento eventi e pipeline in tempo reale.
from datetime import datetime, date, timezone
print(date.today())
print(datetime.now())
print(datetime.now(tz=timezone.utc)) # Python 3.12+ preferred
Questi ti restituiscono l’ora di sistema corrente in ora locale o UTC, a seconda delle necessità.
datetime.fromtimestamp(1700000000)
datetime.utcfromtimestamp(1700000000)
Questi convertono i timestamp epoch in oggetti datetime. Sono estremamente comuni quando si analizzano valori da API o database.
Parsing da stringhe
Nei dataset reali i timestamp sono spesso memorizzati come testo. Python offre strumenti affidabili per convertire quelle stringhe in valori strutturati.
strptime()
from datetime import datetime
dt = datetime.strptime("2025-03-01 14:30", "%Y-%m-%d %H:%M")
print(dt)
strptime() analizza una stringa usando un pattern di formattazione. Se la stringa non corrisponde esattamente, Python genera ValueError.
from datetime import datetime
dt = datetime.strptime("not-a-date", "%Y-%m-%d")
Questo fallirebbe perché l’input non corrisponde al pattern previsto.
fromisoformat()
datetime.fromisoformat("2025-03-01T14:30:00")
Le stringhe ISO 8601 si analizzano senza problemi perché la struttura è standardizzata. Spesso è il modo più semplice per caricare timestamp da API o pipeline dati moderne.
Eseguire operazioni aritmetiche sulle date
Una volta che sai creare i timestamp, il passo successivo è lavorarci. Puoi farlo calcolando durate, spostando date o confrontando intervalli.
Timedelta per i calcoli temporali
timedelta modella periodi a durata fissa come “5 ore” o “2 settimane”. Questi periodi sono utili per scheduling, logging e per semplici countdown.
from datetime import datetime, timedelta
dt = datetime(2025, 3, 1, 14, 30)
new_dt = dt + timedelta(days=5)
print(new_dt)
Questo esempio sposta il timestamp avanti di cinque giorni.
start = datetime(2025, 3, 1, 9, 0)
end = datetime(2025, 3, 1, 14, 30)
duration = end - start
print(duration.total_seconds())
Qui, sottrarre due datetime restituisce un timedelta, che puoi convertire in secondi, giorni o ore.
Durata fissa vs. aritmetica consapevole del calendario
Non tutte le unità di tempo sono uguali. I mesi variano in lunghezza, gli anni possono avere giorni bisestili e il comportamento di fine mese può essere imprevedibile. Per questi scenari, timedelta non basta.
dateutil.relativedelta gestisce l’aritmetica “consapevole del calendario”:
from dateutil.relativedelta import relativedelta
from datetime import date
d = date(2025, 1, 31)
print(d + relativedelta(months=1))
Questo gestisce correttamente lo scenario del mancante “31 febbraio” spostando la data in modo appropriato.
Formattare e analizzare le date
La formattazione dei datetime è ovunque: le API richiedono formati specifici, gli utenti preferiscono testo leggibile e i log dipendono da stringhe temporali coerenti. Python supporta sia formattazioni flessibili sia rappresentazioni standardizzate.
Formattazione delle stringhe con strftime
strftime() ti permette di trasformare oggetti datetime in stringhe formattate usando codici predefiniti.
from datetime import datetime
dt = datetime(2025, 3, 1, 14, 30)
print(dt.strftime("%A, %B %d, %Y at %H:%M"))
Questo stampa una stringa leggibile con il giorno della settimana e il nome completo del mese.
dt.strftime("%Y-%m-%dT%H:%M:%S")
Questo produce una stringa in stile ISO adatta all’archiviazione dei dati o alle API.
Parsing di stringhe con strptime
from datetime import datetime
dt = datetime.strptime("2025-03-01 14:30", "%Y-%m-%d %H:%M")
print(dt)
Questo converte il testo in un oggetto datetime. Qualsiasi mancata corrispondenza tra stringa e pattern genera un errore.
Lavorare con ISO 8601 e RFC 3339
ISO 8601 risolve l’ambiguità presente in molti formati di data regionali. Python lo supporta nativamente:
from datetime import datetime
dt = datetime.fromisoformat("2025-03-01T14:30:00")
print(dt.isoformat())
Questo è il formato più sicuro quando si scambiano dati tra sistemi, API o database.
Gestione dei fusi orari
I fusi orari introducono alcune delle sfide più insidiose nella programmazione temporale. Python aiuta distinguendo tra oggetti datetime naïve e aware e fornendo strumenti per la gestione dei fusi nel mondo reale.
Oggetti datetime naïve vs. aware
Un datetime naïve non ha fuso orario:
from datetime import datetime
naive_dt = datetime(2025, 3, 1, 14, 30)
print(naive_dt.tzinfo) # None
Un datetime aware include un offset di fuso orario:
from datetime import timezone, timedelta
aware_dt = naive_dt.replace(tzinfo=timezone(timedelta(hours=1)))
print(aware_dt)
Mescolare valori naïve e aware in confronti o operazioni aritmetiche solitamente causa errori.
Uso del modulo zoneinfo
Il modulo zoneinfo di Python fornisce accesso ai fusi orari IANA reali:
from zoneinfo import ZoneInfo
from datetime import datetime
dt = datetime(2025, 3, 1, 14, 30, tzinfo=ZoneInfo("Europe/Paris"))
print(dt)
La conversione di fuso orario è semplice:
dt.astimezone(ZoneInfo("America/New_York"))
Questo esprime lo stesso momento in un diverso fuso orario locale.
Conversione tra fusi orari
Puoi convertire qualsiasi timestamp aware in un altro fuso usando astimezone():
from zoneinfo import ZoneInfo
dt_ny = dt.astimezone(ZoneInfo("America/New_York"))
print(dt_ny)
Una buona pratica comune è memorizzare i timestamp in UTC e convertire solo quando serve per la visualizzazione.
Confrontare e filtrare le date
I confronti compaiono in quasi tutti i flussi di lavoro. Pensa all’ordinamento dei log, al filtraggio degli eventi o a stabilire se qualcosa è avvenuto prima o dopo una soglia.
from datetime import datetime
a = datetime(2025, 3, 1, 12, 0)
b = datetime(2025, 3, 1, 15, 0)
print(a < b) # True
I confronti tra oggetti consapevoli del fuso tengono conto degli offset:
from datetime import datetime
from zoneinfo import ZoneInfo
dt1 = datetime(2025, 3, 1, 12, 0, tzinfo=ZoneInfo("Europe/London"))
dt2 = datetime(2025, 3, 1, 7, 0, tzinfo=ZoneInfo("America/New_York"))
print(dt1 == dt2) # True — same moment in time
Il filtraggio delle collezioni è naturale:
dates = [
datetime(2025, 3, 1, 10),
datetime(2025, 2, 20, 9),
datetime(2025, 3, 1, 8)
]
cutoff = datetime(2025, 3, 1)
filtered = [d for d in dates if d >= cutoff]
print(filtered)
La normalizzazione in UTC è utile quando si lavora tra fusi orari diversi.
Casi d’uso più avanzati
Datetime compare in molti flussi di lavoro oltre al semplice parsing e all’aritmetica. Ecco alcuni schemi che incontrerai spesso.
Timestamp Unix
I timestamp Unix misurano i secondi dal 1° gennaio 1970 (UTC). Sono ampiamente utilizzati nella programmazione di sistema e nelle API.
from datetime import datetime
dt = datetime.fromtimestamp(1700000000)
print(dt)
Millisecondi e microsecondi richiedono una scalatura:
ts_ms = 1700000000000
dt_ms = datetime.fromtimestamp(ts_ms / 1000)
ts_us = 1700000000000000
dt_us = datetime.fromtimestamp(ts_us / 1_000_000)
Scheduling e timer
Librerie come schedule dipendono dai valori datetime per determinare quando eseguire i task. Che tu stia attivando funzioni ogni pochi secondi o pianificando un evento singolo più tardi nella giornata, datetime fornisce le basi per quei confronti.
Pattern per l’analisi dei dati
Gli attributi dei datetime vengono spesso estratti per raggruppamenti e analisi basate sul tempo:
dt = datetime(2025, 3, 1, 14, 30)
print(dt.year)
print(dt.isocalendar())
In pandas, il resampling per periodo è estremamente comune:
import pandas as pd
df = pd.DataFrame({
"value": [10, 12, 15],
"timestamp": pd.to_datetime([
"2025-03-01",
"2025-03-02",
"2025-03-08"
])
}).set_index("timestamp")
print(df.resample("W").sum())
Conclusione
Per saperne di più su datetime, dai un'occhiata a questo video dal nostro corso Working with Dates and Times in Python di Max Shrom e Data Types for Data Science in Python di Jason Myers.
Potresti anche trovare utile il nostro tutorial Converting Strings to Dates as datetime Objects se ti serve un piccolo aiuto extra per convertire stringhe.
Technical writer specializzato in AI, ML e data science: rende idee complesse chiare e accessibili.


