Come abbinare date e orari con le espressioni regolari in Python

In questo articolo spiegherò come utilizzare le espressioni regolari in Python per estrarre date e orari dai dati di testo. Le espressioni regolari sono uno strumento potente che consente di rilevare in modo efficiente stringhe con un formato specifico attraverso il pattern matching. Tratteremo le basi delle espressioni regolari, passando attraverso applicazioni più avanzate, e mostreremo come abbinare date e orari con precisione in Python, con esempi concreti.

Indice

Cosa sono le espressioni regolari

Le espressioni regolari (Regular Expression) sono stringhe speciali utilizzate per definire pattern in altre stringhe. Vengono usate per esprimere combinazioni o ripetizioni di caratteri, e vengono impiegate nella ricerca, sostituzione ed estrazione di stringhe. Sono ampiamente utilizzate in programmazione e nell’elaborazione del testo, rappresentando uno strumento potente per manipolare i dati in modo efficiente e flessibile.

Modulo delle espressioni regolari di Python

In Python, il modulo standard per lavorare con le espressioni regolari è il modulo «re». Questo modulo consente di eseguire facilmente operazioni di ricerca, sostituzione, divisione e matching delle stringhe. Di seguito presenteremo le modalità di utilizzo di base e le principali funzioni di questo modulo.

Utilizzo di base

Per utilizzare le espressioni regolari, prima di tutto bisogna importare il modulo «re». Successivamente, si crea il pattern dell’espressione regolare e si utilizzano le sue funzioni per manipolare le stringhe.

import re

# Compilare il pattern dell'espressione regolare
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')

# Eseguire il matching
match = pattern.match('2023-06-16')
if match:
    print("Match trovato:", match.group())

Funzioni principali

  • re.match(): Controlla se l’inizio di una stringa corrisponde al pattern.
  • re.search(): Cerca l’intera stringa e restituisce il primo match trovato.
  • re.findall(): Restituisce una lista di tutte le sottostringhe che corrispondono al pattern.
  • re.sub(): Sostituisce le sottostringhe che corrispondono al pattern.

Matching delle date

Per fare il matching delle date, l’espressione regolare cambia in base al formato della data. In questo esempio vedremo come fare il matching di un formato di data comune, ovvero «YYYY-MM-DD». Questo formato è composto da anno (4 cifre), mese (2 cifre) e giorno (2 cifre).

Matching di una data di base

Il seguente pattern dell’espressione regolare fa il matching di una data nel formato «YYYY-MM-DD».

import re

# Creare il pattern dell'espressione regolare
date_pattern = re.compile(r'\b\d{4}-\d{2}-\d{2}\b')

# Testo di esempio
text = "La data di oggi è 2023-06-16."

# Eseguire il matching
matches = date_pattern.findall(text)
if matches:
    print("Data trovata:", matches)
else:
    print("Data non trovata.") 

Questo pattern corrisponde a 4 cifre numeriche (\d{4}), seguite da un trattino (-), 2 cifre numeriche (\d{2}), un altro trattino e infine altre 2 cifre numeriche (\d{2}). L’uso di \b indica il confine della parola, assicurando che non ci siano altri caratteri prima o dopo la data.

Esempio avanzato: matching di più formati di data

Per fare il matching di più formati di data, è possibile combinare vari pattern. Ad esempio, per includere anche i formati «YYYY/MM/DD» o «YYYY.MM.DD», si può fare come segue.

# Combinazione di più pattern
date_pattern = re.compile(r'\b\d{4}[-/\.]\d{2}[-/\.]\d{2}\b')

# Testo di esempio
text = "Le date sono 2023-06-16, ieri 2023/06/15 e domani 2023.06.17."

# Eseguire il matching
matches = date_pattern.findall(text)
if matches:
    print("Data trovata:", matches)
else:
    print("Data non trovata.") 

Questo pattern riconosce i trattini (-), le barre (/) e i punti (.) come delimitatori.

Matching degli orari

Le espressioni regolari per fare il matching degli orari cambiano a seconda del formato dell’orario. In questo esempio, vedremo come fare il matching di un formato orario comune «HH:MM:SS», composto da ore (2 cifre), minuti (2 cifre) e secondi (2 cifre).

Matching di un orario di base

Il seguente pattern dell’espressione regolare fa il matching di un orario nel formato «HH:MM:SS».

import re

# Creare il pattern dell'espressione regolare
time_pattern = re.compile(r'\b\d{2}:\d{2}:\d{2}\b')

# Testo di esempio
text = "L'orario corrente è 14:30:45."

# Eseguire il matching
matches = time_pattern.findall(text)
if matches:
    print("Orario trovato:", matches)
else:
    print("Orario non trovato.") 

Questo pattern corrisponde a 2 cifre numeriche (\d{2}), seguite dai due punti (:), altre 2 cifre numeriche, altri due punti e altre 2 cifre numeriche. L’uso di \b indica il confine della parola, assicurando che non ci siano altri caratteri prima o dopo l’orario.

Esempio avanzato: matching di orari in formato 24 ore e 12 ore

Per fare il matching di orari sia in formato 24 ore che in formato 12 ore, bisogna includere la gestione di AM/PM.

# Matching per formato 24 ore e 12 ore
time_pattern = re.compile(r'\b((1[0-2]|0?[1-9]):[0-5][0-9](\s?[APap][Mm])?|([01][0-9]|2[0-3]):[0-5][0-9])\b')

# Testo di esempio
text = "L'orario corrente è 14:30, la riunione del mattino è alle 10:00 AM, e quella pomeridiana alle 02:00 PM."

# Eseguire il matching
matches = time_pattern.findall(text)
if matches:
    print("Orari trovati:", [match[0] for match in matches])
else:
    print("Orario non trovato.") 

Questo pattern riconosce i seguenti formati di orario:

  • Orari in formato 24 ore (ad esempio: 14:30)
  • Orari in formato 12 ore (ad esempio: 10:00 AM, 02:00 PM)

Esempio avanzato: conversione di formato di data e orario

In questo esempio vedremo come estrarre una data e un orario usando le espressioni regolari e poi convertirli in un formato differente. Convertemo il formato «YYYY-MM-DD HH:MM:SS» in «MM/DD/YYYY hh:mm AM/PM».

Estrazione di data e orario

Per prima cosa, estraiamo la data e l’orario dal testo usando le espressioni regolari.

import re

# Creare il pattern dell'espressione regolare
datetime_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})')

# Testo di esempio
text = "L'evento inizia il 2023-06-16 14:30:45."

# Eseguire il matching
match = datetime_pattern.search(text)
if match:
    year, month, day, hour, minute, second = match.groups()
    print("Data e orario estratti:", match.group())
else:
    print("Data e orario non trovati.") 

Implementazione della conversione del formato

Ora converte la data e l’orario estratti nel formato «MM/DD/YYYY hh:mm AM/PM».

# Determinare AM/PM
hour = int(hour)
if hour >= 12:
    period = "PM"
    if hour > 12:
        hour -= 12
else:
    period = "AM"
    if hour == 0:
        hour = 12

# Convertire al nuovo formato
formatted_datetime = f"{month}/{day}/{year} {hour:02}:{minute} {period}"
print("Data e orario convertiti:", formatted_datetime)

Questo codice converte un orario in formato 24 ore in formato 12 ore e aggiunge AM/PM per generare il nuovo formato.

Esercizi: Estrazione di date e orari

Per approfondire la comprensione delle espressioni regolari, proviamo a risolvere alcuni esercizi. Lavorando su questi esempi, potrai acquisire esperienza pratica con le espressioni regolari.

Esercizio 1: Estrazione di una singola data

Creare un’espressione regolare per estrarre una data nel formato «YYYY-MM-DD» dal seguente testo.

text = "La scadenza è il 2024-07-20. Il progetto è iniziato il 2024-06-01." 

Soluzione

import re

date_pattern = re.compile(r'\b\d{4}-\d{2}-\d{2}\b')
dates = date_pattern.findall(text)
print("Date estratte:", dates)

Esercizio 2: Estrazione di più orari

Creare un’espressione regolare per estrarre tutti gli orari nel formato «HH:MM:SS» dal seguente testo.

text = "La colazione è alle 07:30:00, il pranzo alle 12:00:00, la cena alle 19:45:00." 

Soluzione

import re

time_pattern = re.compile(r'\b\d{2}:\d{2}:\d{2}\b')
times = time_pattern.findall(text)
print("Orari estratti:", times)

Esercizio 3: Estrazione della data e dell’orario e conversione del formato

Estrai la data e l’orario nel formato «YYYY-MM-DD HH:MM:SS» dal testo seguente e convertilo nel formato «MM/DD/YYYY hh:mm AM/PM».

text = "La riunione inizierà il 2024-06-16 14:30:45." 

Soluzione

import re

# Creare il pattern dell'espressione regolare
datetime_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})')

# Eseguire il matching
match = datetime_pattern.search(text)
if match:
    year, month, day, hour, minute, second = match.groups()

    # Determinare AM/PM
    hour = int(hour)
    if hour >= 12:
        period = "PM"
        if hour > 12:
            hour -= 12
    else:
        period = "AM"
        if hour == 0:
            hour = 12

    # Convertire al nuovo formato
    formatted_datetime = f"{month}/{day}/{year} {hour:02}:{minute} {period}"
    print("Data e orario convertiti:", formatted_datetime)
else:
    print("Data e orario non trovati.") 

Errori comuni e soluzioni

Durante l’uso delle espressioni regolari, è possibile imbattersi in alcuni errori comuni. Comprendere questi errori e affrontarli correttamente permette di migliorare l’accuratezza e l’efficienza delle espressioni regolari.

Errore 1: Matching troppo “avidità”

Il matching “avidità” (greedy matching) cerca di abbinare la stringa più lunga possibile, il che può portare a risultati indesiderati.

Soluzione: utilizzare il matching non avidità

Usare il matching non avidità (lazy matching) per abbinare solo la parte necessaria della stringa. Utilizzare *? o +? per rendere il matching non avidità.

import re

text = "Start123End456End"
pattern = re.compile(r'Start.*?End')

matches = pattern.findall(text)
print("Matching non avidità:", matches)

Errore 2: Uso errato dei caratteri di escape

Se si utilizzano caratteri con un significato speciale nelle espressioni regolari (come . o *), questi potrebbero non comportarsi come ci si aspetta.

Soluzione: usare correttamente i caratteri di escape

Per utilizzare i caratteri speciali come normali caratteri, bisogna fare uso del backslash (\) per l’escape.

import re

text = "Il nome del file è example.txt."
pattern = re.compile(r'example\.txt')

matches = pattern.findall(text)
print("Uso del carattere di escape:", matches)

Errore 3: Diminuzione delle performance dovuta alla complessità del pattern

Pattern complessi possono ridurre le performance e aumentare il tempo di esecuzione.

Soluzione: ottimizzare il pattern

Creare pattern semplici ed efficienti per migliorare le performance. Evitare gruppi di cattura inutili e cercare di abbinare solo ciò che è strettamente necessario.

import re

# Pattern complesso
complex_pattern = re.compile(r'(\d{1,4})-?(\d{1,2})-?(\d{1,2})')

# Pattern ottimizzato
optimized_pattern = re.compile(r'\d{1,4}-\d{1,2}-\d{1,2}') 

Errore 4: Malintesi nei risultati del matching

Se non si comprendono correttamente i risultati del matching delle espressioni regolari, potrebbero esserci fraintendimenti nei dati estratti.

Soluzione: usare gli oggetti di matching

Usare gli oggetti di matching per ottenere esattamente le sottostringhe e i gruppi di cattura abbinati.

import re

text = "La data di oggi è 2024-07-20."
pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')

match = pattern.search(text)
if match:
    year, month, day = match.groups()
    print(f"Data estratta: Anno={year}, Mese={month}, Giorno={day}")
else:
    print("Data non trovata.") 

Conclusioni

Le espressioni regolari sono uno strumento potente per abbinare in modo efficiente stringhe con formati specifici, come date e orari. Utilizzando il modulo «re» di Python, è possibile eseguire operazioni complesse su stringhe in modo semplice ed efficace. In questo articolo abbiamo visto l’utilizzo di base delle espressioni regolari, il matching delle date e degli orari, esempi avanzati, esercizi pratici e come affrontare errori comuni. Usare correttamente le espressioni regolari può migliorare notevolmente l’accuratezza e l’efficienza nel trattamento dei dati.

Indice