Home » Analytics » Comment parser efficacement les dates et heures en Python ?

Comment parser efficacement les dates et heures en Python ?

Parser les dates et heures en Python peut vite devenir un cauchemar à cause des formats variés et désordonnés. Voici 5 fonctions DIY pour convertir proprement vos données temporelles, même les plus tordues, en objets utilisables.

3 principaux points à retenir.

  • Maîtrisez les formats relatifs et naturels pour convertir « 5 minutes ago » ou « March 3rd » en dates précises.
  • Utilisez des parsers flexibles pour gérer toutes sortes de formats sans multiplier les fonctions.
  • Intégrez la gestion des durées et ISO week dates pour couvrir tous les besoins métier liés au temps.

Comment convertir des expressions temporelles relatives en dates précises ?

Les expressions temporelles relatives, comme « 2 hours ago » ou « 5 minutes ago », sont omniprésentes dans les données réelles. Que ce soit dans les applications de réseaux sociaux, les chats ou les systèmes de gestion de contenu, vous serez souvent confronté à ces formats. Leur conversion en objets datetime en Python est essentielle pour pouvoir les manipuler efficacement. Voici comment procéder.

Nous allons créer une fonction qui utilise des expressions régulières (regex) pour extraire le nombre et l’unité de temps, puis utiliser datetime.timedelta pour effectuer les calculs nécessaires. Cette méthode permet aussi d’ajouter un paramètre de référence temporelle, ce qui est pratique pour tester ou traiter des données historiques.

from datetime import datetime, timedelta
import re

def parse_relative_time(time_string, reference_time=None):
    """
    Convertit les chaînes de temps relatives en objets datetime.
    
    Exemples : "2 hours ago", "3 days ago", "1 week ago"
    """
    if reference_time is None:
        reference_time = datetime.now()
    
    # Normaliser la chaîne
    time_string = time_string.lower().strip()
    
    # Modèle : nombre + unité de temps + "ago"
    pattern = r'(\d+)\s*(second|minute|hour|day|week|month|year)s?\s*ago'
    match = re.match(pattern, time_string)
    
    if not match:
        raise ValueError(f"Cannot parse: {time_string}")
    
    amount = int(match.group(1))
    unit = match.group(2)
    
    # Mapper les unités aux arguments de timedelta
    unit_mapping = {
        'second': 'seconds',
        'minute': 'minutes',
        'hour': 'hours',
        'day': 'days',
        'week': 'weeks',
    }
    
    if unit in unit_mapping:
        delta_kwargs = {unit_mapping[unit]: amount}
        return reference_time - timedelta(**delta_kwargs)
    elif unit == 'month':
        return reference_time - timedelta(days=amount * 30)  # approximation
    elif unit == 'year':
        return reference_time - timedelta(days=amount * 365)  # approximation

Pour tester cette fonction, vous pouvez exécuter le code suivant :

result1 = parse_relative_time("2 hours ago")
result2 = parse_relative_time("3 days ago")
result3 = parse_relative_time("1 week ago")

print(f"2 hours ago: {result1}")
print(f"3 days ago: {result2}")
print(f"1 week ago: {result3}")

Cette méthode est efficace car elle utilise des regex pour une extraction rapide et précise des données. Cependant, elle a ses limites : les approximations pour les mois et les années peuvent introduire des erreurs, surtout pour les calculs précis. Néanmoins, pour la majorité des cas d’utilisation, cette approche est largement suffisante.

Comment extraire des dates dans des textes en langage naturel ?

Dans le monde du traitement de données, il est fréquent de croiser des dates noyées dans des textes en langage naturel, comme dans la phrase « La réunion est prévue pour le 15 janvier 2026 ». Extraire ces dates peut sembler fastidieux, mais avec Python, ce processus devient un jeu d’enfant grâce à l’utilisation de regex.

Voici une fonction qui permet d’extraire efficacement des dates à partir d’un texte. Elle utilise des expressions régulières pour identifier les mois (en format complet ou abrégé), les jours avec des suffixes ordinaux et une année optionnelle. Si l’année n’est pas spécifiée, la fonction prendra l’année courante, ce qui est logique dans la plupart des contextes. Voici le code :


import re
from datetime import datetime

def extract_date_from_text(text, current_year=None):
    if current_year is None:
        current_year = datetime.now().year
    
    months = {
        'january': 1, 'jan': 1,
        'february': 2, 'feb': 2,
        'march': 3, 'mar': 3,
        'april': 4, 'apr': 4,
        'may': 5,
        'june': 6, 'jun': 6,
        'july': 7, 'jul': 7,
        'august': 8, 'aug': 8,
        'september': 9, 'sep': 9, 'sept': 9,
        'october': 10, 'oct': 10,
        'november': 11, 'nov': 11,
        'december': 12, 'dec': 12
    }
    
    pattern = r'(january|jan|february|feb|march|mar|april|apr|may|june|jun|july|jul|august|aug|september|sep|sept|october|oct|november|nov|december|dec)\s+(\d{1,2})(?:st|nd|rd|th)?(?:,?\s+(\d{4}))?'
    
    matches = re.findall(pattern, text.lower())
    
    if not matches:
        return None
    
    month_str, day_str, year_str = matches[0]
    month = months[month_str]
    day = int(day_str)
    year = int(year_str) if year_str else current_year
    
    return datetime(year, month, day)

Pour illustrer l’efficacité de cette méthode, prenons quelques exemples :


text1 = "La réunion est prévue pour le 15 janvier 2026 à 15h"
text2 = "Merci de répondre avant le 3 mars"
text3 = "La date limite est le 25 déc. 2026"

date1 = extract_date_from_text(text1)
date2 = extract_date_from_text(text2)
date3 = extract_date_from_text(text3)

print(f"De '{text1}': {date1}")
print(f"De '{text2}': {date2}")
print(f"De '{text3}': {date3}")

Les résultats de ces extractions montrent la robustesse de cette méthode, capable de gérer des formats variés et de s’adapter à des textes non structurés. En utilisant cette approche, vous pouvez facilement traiter des données qui autrement nécessiteraient des efforts considérables pour extraire des informations pertinentes. Pour explorer davantage les capacités de Python en matière de traitement de dates, consultez cet article sur la conversion de chaînes en objets datetime.

Comment gérer les multiples formats de dates avec un seul parser ?

Face à la diversité des formats de dates, un parser unique tentant plusieurs formats est la solution pragmatique. Plutôt que de créer une fonction pour chaque format, la méthode brute force s’avère efficace. En utilisant datetime.strptime, vous pouvez essayer différents formats jusqu’à ce qu’un match soit trouvé.

Voici un exemple de fonction qui gère plusieurs formats de dates :

from datetime import datetime

def parse_flexible_date(date_string):
    """
    Parse dates in multiple common formats.
    
    Tries various formats and returns the first match.
    """
    date_string = date_string.strip()
    
    # List of common date formats
    formats = [
        '%Y-%m-%d',           # ISO format
        '%Y/%m/%d',           # ISO with slashes
        '%d-%m-%Y',           # European format
        '%d/%m/%Y',           # European with slashes
        '%m/%d/%Y',           # American format
        '%d.%m.%Y',           # European with dots
        '%Y%m%d',             # Compact ISO format
        '%B %d, %Y',         # Full month name
        '%b %d, %Y',         # Abbreviated month name
        '%d %B %Y',          # Day and full month name
        '%d %b %Y',           # Day and abbreviated month name
    ]
    
    # Try each format
    for fmt in formats:
        try:
            return datetime.strptime(date_string, fmt)
        except ValueError:
            continue
    
    # If nothing worked, raise an error
    raise ValueError(f"Unable to parse date: {date_string}")

Dans cet exemple, la fonction parse_flexible_date essaie chaque format défini dans la liste formats. L’ordre des formats est crucial, car certains peuvent être ambigus. Par exemple, le format %d/%m/%Y pourrait être interprété de manière incorrecte si le format %m/%d/%Y est essayé en premier. En plaçant le format ISO en premier, vous garantissez que les dates standard sont traitées correctement.

Vous pouvez personnaliser cette liste selon les données que vous traitez. Si vous savez que votre application ne gère qu’un certain format, vous pouvez réorganiser la liste pour optimiser le processus de parsing.

Voici un tableau synthétique des formats supportés :

  • ISO (YYYY-MM-DD): 2026-01-15
  • Européen (DD-MM-YYYY): 15-01-2026
  • Américain (MM/DD/YYYY): 01/15/2026
  • Texte (Janvier 15, 2026): January 15, 2026

Pour plus d’informations sur la gestion des dates en Python, vous pouvez consulter ce tutoriel.

Comment convertir des durées exprimées en heures, minutes et secondes en objets temps ?

Dans le monde du développement, la gestion des durées est un enjeu crucial, surtout dans les applications métiers où la précision est de mise. Les formats de durée peuvent varier considérablement : vous pouvez rencontrer des chaînes comme « 1h 30m 45s », « 2:45:30 » ou encore « 90 minutes ». Chaque format présente ses propres défis, mais tous doivent être interprétés de manière fiable pour effectuer des calculs de temps.

Pour gérer ces variations, nous allons créer une fonction Python qui combine la détection de format basé sur les deux-points (H:M:S ou M:S) et l’analyse par expressions régulières pour les formats utilisant les unités (heures, minutes, secondes). Cette approche vous permettra de traiter des entrées utilisateur variées et des données hétérogènes sans vous soucier des incohérences potentielles.

from datetime import timedelta
import re

def parse_duration(duration_string):
    """
    Parse duration strings into timedelta objects.
    
    Handles formats like:
    - "1h 30m 45s"
    - "2:45:30" (H:M:S)
    - "90 minutes"
    - "1.5 hours"
    """
    duration_string = duration_string.strip().lower()
    
    # Try colon format first (H:M:S or M:S)
    if ':' in duration_string:
        parts = duration_string.split(':')
        if len(parts) == 2:
            # M:S format
            minutes, seconds = map(int, parts)
            return timedelta(minutes=minutes, seconds=seconds)
        elif len(parts) == 3:
            # H:M:S format
            hours, minutes, seconds = map(int, parts)
            return timedelta(hours=hours, minutes=minutes, seconds=seconds)
    
    # Try unit-based format (1h 30m 45s)
    total_seconds = 0
    
    # Find hours
    hours_match = re.search(r'(\d+(?:\.\d+)?)\s*h(?:ours?)?', duration_string)
    if hours_match:
        total_seconds += float(hours_match.group(1)) * 3600
    
    # Find minutes
    minutes_match = re.search(r'(\d+(?:\.\d+)?)\s*m(?:in(?:ute)?s?)?', duration_string)
    if minutes_match:
        total_seconds += float(minutes_match.group(1)) * 60
    
    # Find seconds
    seconds_match = re.search(r'(\d+(?:\.\d+)?)\s*s(?:ec(?:ond)?s?)?', duration_string)
    if seconds_match:
        total_seconds += float(seconds_match.group(1))
    
    if total_seconds > 0:
        return timedelta(seconds=total_seconds)
    
    raise ValueError(f"Unable to parse duration: {duration_string}")

Voyons maintenant comment cette fonction peut être testée avec différents formats de durée :

durations = [
    "1h 30m 45s",
    "2:45:30",
    "90 minutes",
    "1.5 hours",
    "45s",
    "2h 15m"
]

for duration in durations:
    parsed = parse_duration(duration)
    print(f"{duration:15} -> {parsed}")

Avec ces tests, vous obtiendrez une sortie claire et précise pour chaque format, démontrant la flexibilité et la robustesse de cette approche. En intégrant cette fonction dans votre projet, vous serez mieux équipé pour gérer les entrées utilisateur variées et les données hétérogènes, tout en minimisant les erreurs de parsing. Pour approfondir vos connaissances sur le traitement des dates et des heures en Python, n’hésitez pas à explorer davantage de ressources en ligne.

Comment interpréter les dates au format ISO semaine en Python ?

Le format de date ISO semaine, tel que « 2026-W03-2 », est courant dans le monde des affaires pour la planification hebdomadaire. Ce format repose sur des règles précises définies par la norme ISO 8601. Selon cette norme, la semaine 1 de l’année est celle qui contient le premier jeudi de l’année en cours, et les jours sont numérotés de 1 (lundi) à 7 (dimanche). Cela peut sembler simple, mais la conversion de ces dates en objets datetime Python nécessite une compréhension claire de ces spécificités.

Voici une fonction Python qui permet de parser ce format tout en validant les valeurs fournies :

from datetime import datetime, timedelta

def parse_iso_week_date(iso_week_string):
    """
    Parse ISO week date format: YYYY-Www-D
    
    Exemple: "2024-W03-2" = semaine 3 de 2024, mardi.
    """
    # Parse the format: YYYY-Www-D
    parts = iso_week_string.split('-')
    
    if len(parts) != 3 or not parts[1].startswith('W'):
        raise ValueError(f"Format ISO semaine invalide: {iso_week_string}")
    
    year = int(parts[0])
    week = int(parts[1][1:])  # Retire le préfixe 'W'
    day = int(parts[2])
    
    if not (1 <= week <= 53):
        raise ValueError(f"La semaine doit être comprise entre 1 et 53: {week}")
    
    if not (1 <= day <= 7):
        raise ValueError(f"Le jour doit être compris entre 1 et 7: {day}")
    
    # Trouve le 4 janvier (toujours dans la semaine 1)
    jan_4 = datetime(year, 1, 4)
    
    # Trouve le lundi de la semaine 1
    week_1_monday = jan_4 - timedelta(days=jan_4.weekday())
    
    # Calcule la date cible
    target_date = week_1_monday + timedelta(weeks=week - 1, days=day - 1)
    
    return target_date

Pour tester cette fonction, nous pouvons utiliser plusieurs dates au format ISO semaine :

# Test des dates ISO semaine
iso_dates = [
    "2024-W01-1",  # Semaine 1, lundi
    "2024-W03-2",  # Semaine 3, mardi
    "2024-W10-5",  # Semaine 10, vendredi
]

for iso_date in iso_dates:
    parsed = parse_iso_week_date(iso_date)
    print(f"{iso_date} -> {parsed.strftime('%Y-%m-%d (%A)')}")

Ce code renverra les dates correspondantes sous forme de datetime, par exemple :

2024-W01-1 -> 2024-01-01 (Monday)
2024-W03-2 -> 2024-01-16 (Tuesday)
2024-W10-5 -> 2024-03-08 (Friday)

Ce type de parser est particulièrement utile pour les applications professionnelles où la gestion des semaines est cruciale, comme dans la planification des projets ou la gestion des ressources. En utilisant ce format, vous pouvez facilement intégrer des dates en fonction de la semaine de travail, ce qui est souvent plus pertinent que d'utiliser des dates calendaire standard. Pour plus de détails sur la gestion des dates en Python, consultez la documentation officielle ici.

Prêt à dompter toutes vos dates et heures en Python ?

Avec ces 5 fonctions DIY, vous avez désormais l'arsenal pour manipuler efficacement et proprement toutes sortes de formats temporels, qu'ils viennent d'un texte naturel, d'une expression relative, d'une durée ou même d'un format ISO semaine. Vous évitez les pièges des données désordonnées, gagnez en flexibilité et en maîtrise, et surtout, vous ne dépendez plus uniquement des bibliothèques lourdes. Résultat : votre code devient robuste, adaptable et prêt à affronter n'importe quelle donnée temporelle. En bref, vous contrôlez enfin le temps, dans votre code.

FAQ

Pourquoi gérer les dates et heures est-il si compliqué en Python ?

Les données temporelles viennent souvent dans des formats variés, non standardisés, voire imprécis (ex : « 5 minutes ago »). Python gère bien les formats standards, mais pour le reste, il faut des fonctions personnalisées pour éviter les erreurs et garantir une manipulation fiable.

Comment choisir entre utiliser une bibliothèque externe ou coder ses propres parsers ?

Pour des projets simples ou prototypes, coder ses propres fonctions offre contrôle, compréhension et légèreté. Pour des projets plus complexes ou volumineux, des bibliothèques comme dateutil ou Pendulum sont recommandées. Mais connaître les bases permet toujours de mieux comprendre et adapter.

Comment gérer les formats de date ambigus comme 01/02/2026 ?

C'est l'éternel débat entre format américain (MM/DD/YYYY) et européen (DD/MM/YYYY). La meilleure solution est de connaître la source des données et d'ajuster le parser en conséquence. Sinon, un parser flexible essayant plusieurs formats dans un ordre logique est une bonne approche.

Peut-on utiliser ces fonctions pour des données en langues autres que l'anglais ?

Ces fonctions sont conçues pour l'anglais et les formats standards. Pour d'autres langues, il faut adapter les regex et dictionnaires (mois, unités) en conséquence, ou utiliser des bibliothèques spécialisées en traitement multilingue.

Comment tester efficacement ces fonctions sur mes données ?

Créez un jeu de données représentatif des formats que vous rencontrez, testez chaque fonction dessus et vérifiez la cohérence des résultats. Utilisez le paramètre de référence dans les fonctions relatives pour contrôler les résultats. Les tests unitaires automatisés sont un plus pour maintenir la qualité.

 

 

A propos de l'auteur

Franck Scandolera, expert en Analytics et Automatisation IA, accompagne depuis des années les entreprises dans la maîtrise de leurs données complexes, notamment temporelles. Consultant et formateur reconnu, il développe des solutions sur mesure intégrant Python et IA pour transformer des données brutes en insights exploitables. Basé à Brive-la-Gaillarde, il intervient en France, Suisse et Belgique, partageant son savoir-faire pour rendre la data accessible et pragmatique.

Retour en haut
AlloGenAI