Parser les dates et heures en Python peut vite tourner au cauchemar avec des formats variés et du texte bruité. Utiliser des fonctions DIY adaptées vous simplifie la vie face à ces données capricieuses. Découvrez comment maîtriser ces conversions pour des données propres et exploitables.
3 principaux points à retenir.
- Maîtrisez les formats relatifs et naturels pour convertir « 2 heures ago » ou « March 3rd » en objets datetime précis.
- Adoptez des parsers flexibles capables de gérer plusieurs formats courants automatiquement, sans code redondant.
- Intégrez la gestion des durées et formats ISO pour couvrir tous vos besoins, des durées utilisateur aux dates business ISO week.
Comment gérer les dates relatives en Python
Les dates relatives, comme « il y a 5 minutes », sont omniprésentes sur les réseaux sociaux et dans les applications de messagerie. Pourtant, leur conversion en objets datetime en Python peut être un vrai casse-tête. La plupart du temps, ces formats ne sont pas pris en charge par les bibliothèques standards, et c’est là que notre fonction entre en jeu.
Voici une fonction Python qui utilise des expressions régulières (regex) pour extraire le nombre et l’unité de temps, puis les transforme en objets datetime grâce à timedelta.
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 heures ago", "3 jours ago", "1 semaine 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*(seconde|minute|heure|jour|semaine|mois|année)s?\s*ago'
match = re.match(pattern, time_string)
if not match:
raise ValueError(f"Impossible de parser : {time_string}")
amount = int(match.group(1))
unit = match.group(2)
# Mapper les unités aux arguments de timedelta
unit_mapping = {
'seconde': 'seconds',
'minute': 'minutes',
'heure': 'hours',
'jour': 'days',
'semaine': 'weeks',
}
if unit in unit_mapping:
delta_kwargs = {unit_mapping[unit]: amount}
return reference_time - timedelta(**delta_kwargs)
elif unit == 'mois':
# Approximation : 30 jours par mois
return reference_time - timedelta(days=amount * 30)
elif unit == 'année':
# Approximation : 365 jours par an
return reference_time - timedelta(days=amount * 365)
Cette fonction prend en compte des chaînes comme « 2 heures ago » ou « 1 semaine ago », et les convertit en datetime. Vous pouvez tester cette fonction avec plusieurs cas :
result1 = parse_relative_time("2 heures ago")
result2 = parse_relative_time("3 jours ago")
result3 = parse_relative_time("1 semaine ago")
print(f"Il y a 2 heures : {result1}")
print(f"Il y a 3 jours : {result2}")
print(f"Il y a 1 semaine : {result3}")
Les résultats vous donneront des objets datetime correspondant à ces moments passés. Notez que pour les mois et les années, nous faisons des approximations, ce qui est suffisamment précis pour la plupart des applications.
Le paramètre reference_time est particulièrement utile pour tester ou traiter des données historiques. Il vous permet de définir un point de référence différent pour vos calculs. Cependant, gardez à l’esprit que cette fonction n’est pas infaillible. Les dates relatives en langage naturel peuvent varier considérablement, et des formats non standard peuvent nécessiter des ajustements.
Pour approfondir la gestion des dates en Python, je vous recommande cet article intéressant ici.
Comment extraire des dates dans du texte naturel
Extraire des dates cachées dans du texte naturel, comme dans la phrase « la réunion est prévue pour le 15 janvier », n’est pas aussi simple qu’il y paraît. Cela nécessite une approche ciblée pour identifier et extraire correctement les informations pertinentes. La fonction que nous allons examiner utilise un dictionnaire de mois et une expression régulière (regex) pour effectuer cette tâche avec efficacité.
Voici la fonction qui fait le travail :
import re
from datetime import datetime
def extract_date_from_text(text, current_year=None):
"""
Extract dates from natural language text.
Handles formats like:
- "January 15th, 2024"
- "March 3rd"
- "Dec 25th, 2023"
"""
if current_year is None:
current_year = datetime.now().year
# Month names (full and abbreviated)
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: Month Day(st/nd/rd/th), Year (year optional)
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
# Take the first match
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)
La fonction commence par un dictionnaire qui associe les noms de mois à leurs valeurs numériques. Ensuite, elle utilise une regex pour capturer les mois, les jours et les années, en prenant en compte les suffixes ordinals tels que st, nd, rd, et th. Les groupes capturés permettent d’extraire ces informations de manière structurée, ce qui est crucial pour la suite du traitement.
Si l’année n’est pas fournie, la logique de la fonction remplace l’année manquante par l’année courante, ce qui est souvent le cas dans des contextes où une date future est mentionnée sans spécification d’année. Cela garantit que l’extraction reste pertinente, même lorsque l’année n’est pas explicitement indiquée.
Voici quelques exemples pour tester la fonction :
text1 = "La réunion est prévue pour le 15 janvier 2026 à 15h"
text2 = "Merci de répondre d'ici le 3 mars"
text3 = "Échéance : 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}")
Cette approche est particulièrement utile pour le traitement automatique de textes ou d’emails, où les dates peuvent apparaître sous des formats variés. En intégrant cette fonction dans vos scripts, vous pourrez extraire rapidement des informations temporelles essentielles sans avoir à vous soucier des formats spécifiques.
Quelle méthode pour parser plusieurs formats de dates flexibles
Face à la multitude de formats de dates que l’on peut rencontrer dans des projets variés (ISO, français, américain, etc.), un parser unique s’avère indispensable. En effet, la gestion de ces formats disparates peut rapidement devenir un véritable casse-tête si l’on ne dispose pas d’une solution robuste. Voici une fonction qui teste une liste ordonnée de formats en utilisant datetime.strptime, tout en capturant les exceptions pour s’assurer que l’on ne se bloque pas sur un format non géré.
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',
'%Y/%m/%d',
'%d-%m-%Y',
'%d/%m/%Y',
'%m/%d/%Y',
'%d.%m.%Y',
'%Y%m%d',
'%B %d, %Y',
'%b %d, %Y',
'%d %B %Y',
'%d %b %Y',
]
# 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}")
Voici quelques exemples concrets pour illustrer cette fonction :
dates = [
"2026-01-15",
"15/01/2026",
"01/15/2026",
"15.01.2026",
"20260115",
"January 15, 2026",
"15 Jan 2026"
]
for date_str in dates:
parsed = parse_flexible_date(date_str)
print(f"{date_str:20} -> {parsed}")
Chaque format est testé dans l’ordre de la liste, et le premier qui correspond est retourné. C’est ici que l’ordre des formats devient crucial. Par exemple, si vous savez que vos données proviennent d’un contexte international où le format ISO est prédominant, il serait judicieux de le placer en tête de liste. À l’inverse, si vous traitez principalement des données américaines, vous pourriez prioriser les formats comme %m/%d/%Y.
Voici un tableau récapitulatif des formats supportés :
- YYYY-MM-DD : 2026-01-15
- DD-MM-YYYY : 15-01-2026
- MM/DD/YYYY : 01/15/2026
- DD.MM.YYYY : 15.01.2026
- YYYYMMDD : 20260115
- January DD, YYYY : January 15, 2026
- DD Mon YYYY : 15 Jan 2026
Pour plus de détails sur le parsing des dates et heures en Python, explorez cet article ici.
Comment convertir des durées textuelles en objets temps
Les durées au format « 1h 30m 45s » ou « 2:45:30 » sont monnaie courante dans divers domaines, que ce soit pour le suivi des performances sportives, la gestion de vidéos ou encore le suivi du temps de travail. Transformer ces chaînes de caractères en objets timedelta en Python est essentiel pour effectuer des calculs. Voici comment procéder.
Nous allons créer une fonction qui commence par gérer le format colon (H:M:S) avant de passer aux formats basés sur des unités de temps à l'aide d'expressions régulières (regex). Voici le code :
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}")Cette fonction gère deux principaux formats : le format séparé par des deux-points et le format basé sur des unités. Pour le format colon, nous séparons les parties (heures, minutes, secondes) et les interprétons. Pour le format basé sur des unités, nous utilisons des regex pour détecter et accumuler les heures, minutes et secondes. Cela permet également de traiter les durées partielles comme « 45s » ou « 2h 15m » sans nécessiter tous les éléments.
Voici quelques tests pour illustrer la robustesse de notre fonction :
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}")Les résultats nous montrent comment chaque format est correctement converti en timedelta. L'intérêt de cette fonction est évident dans des applications vidéo, sportives ou de suivi de temps où les durées doivent être manipulées avec précision. Pour approfondir ce sujet, vous pouvez consulter ce lien : DataCamp.
Comment parser les dates au format ISO semaine en Python
Le format ISO semaine est un incontournable dans le monde des affaires. Par exemple, une date comme 2026-W03-2 indique la semaine 3 de l’année 2026, et le jour 2 de cette semaine, qui correspond à un mardi. Cette structure est particulièrement utile pour la planification hebdomadaire, car elle permet d’organiser les tâches et les rendez-vous en fonction des semaines plutôt que des dates spécifiques.
Pour comprendre ce format, il est essentiel de connaître la règle ISO qui définit la semaine 1. Selon cette norme, la semaine 1 est celle qui contient le premier jeudi de l’année. Cela signifie qu’une semaine peut commencer en décembre de l’année précédente. Par exemple, si le 1er janvier est un vendredi, la première semaine de l’année ne commencera que le lundi suivant, car elle doit inclure le jeudi de cette semaine.
Pour parser ces dates, nous allons créer une fonction qui découpe la chaîne ISO, valide les valeurs et calcule la date à partir du lundi de la semaine 1, qui est déterminé en trouvant le 4 janvier de l’année concernée. Voici comment cela se présente :
from datetime import datetime, timedelta def parse_iso_week_date(iso_week_string): """ Parse ISO week date format: YYYY-Www-D Example: "2024-W03-2" = Week 3 of 2024, Tuesday """ parts = iso_week_string.split('-') if len(parts) != 3 or not parts[1].startswith('W'): raise ValueError(f"Invalid ISO week format: {iso_week_string}") year = int(parts[0]) week = int(parts[1][1:]) # Remove 'W' prefix day = int(parts[2]) if not (1 <= week <= 53): raise ValueError(f"Week must be between 1 and 53: {week}") if not (1 <= day <= 7): raise ValueError(f"Day must be between 1 and 7: {day}") # Find January 4th (always in week 1) jan_4 = datetime(year, 1, 4) # Find Monday of week 1 week_1_monday = jan_4 - timedelta(days=jan_4.weekday()) # Calculate the target date target_date = week_1_monday + timedelta(weeks=week - 1, days=day - 1) return target_datePour tester cette fonction, prenons quelques exemples :
# Test ISO week dates iso_dates = [ "2024-W01-1", # Week 1, Monday "2024-W03-2", # Week 3, Tuesday "2024-W10-5", # Week 10, Friday ] 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 des dates précises, facilitant ainsi la gestion des données professionnelles. En ayant un parser prêt à l'emploi pour le format ISO semaine, vous évitez des complications inutiles lors de la manipulation de données, surtout dans un contexte où la précision est essentielle. Pour approfondir vos connaissances sur la gestion des dates en Python, vous pouvez consulter la documentation officielle ici.
Vous êtes prêt à dompter toutes les dates et heures en Python, et après ?
Ces fonctions DIY Python sont vos meilleures armes contre les formats de dates et heures chaotiques qu'on rencontre partout. En maîtrisant la conversion des dates relatives, l'extraction dans du texte, le parsing flexible, la gestion des durées et les formats ISO, vous gagnez en robustesse et autonomie. Plus besoin d'attendre des libs lourdes ou des solutions miracles, vous comprenez enfin le mécanisme sous-jacent. Résultat : votre code devient plus fiable, votre traitement des données plus précis, et vous économisez un temps fou. Un vrai plus pour tous vos projets data, IA ou automatisation.
FAQ
Pourquoi parser les dates relatives est-il compliqué ?
Parce que les formats relatifs comme « 2 hours ago » dépendent du contexte temporel actuel et nécessitent une conversion dynamique en datetime pour être exploitables en calculs ou analyses.Comment gérer les formats de dates variés dans un même projet ?
La meilleure méthode est d'utiliser un parser flexible qui teste plusieurs formats courants via des essais successifs, comme avec datetime.strptime, et qui renvoie la première correspondance valide.Peut-on parser une durée exprimée en texte libre ?
Oui, en combinant la détection des formats à deux-points (H:M:S) et l'analyse des unités via regex, on peut convertir des durées comme « 1h 30m » ou « 90 minutes » en objets timedelta exploitables.Qu'est-ce qu'une date ISO semaine et pourquoi l'utiliser ?
Une date ISO semaine indique l'année, la semaine et le jour dans la semaine (lundi à dimanche). Elle est utilisée en business pour planifier et organiser les tâches hebdomadaires de façon standardisée.Ces fonctions DIY remplacent-elles les bibliothèques spécialisées ?
Elles sont parfaites pour des scripts légers, prototypes ou cas spécifiques. Pour des projets complexes ou à grande échelle, des bibliothèques comme dateutil ou Pendulum offrent plus de fonctionnalités et robustesse.
A propos de l'auteur
Consultant et formateur expert en Analytics, Data et Automatisation IA, je m'appelle Franck Scandolera. Fort d'une longue expérience à développer des applications IA et à intégrer l'automatisation dans les workflows métier, je partage ici des solutions concrètes pour maîtriser les données temporelles en Python. Depuis mon agence webAnalyste et mon organisme Formations Analytics, j'accompagne les professionnels à déjouer les pièges des formats de dates et optimiser leurs traitements data.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GTM server, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.






