Guide pratique · PostgreSQL · BigQuery · Snowflake ·

Lecture : ~20 min

Teste ton niveau sur modai-lab.com/test-sql/


Pourquoi ce guide existe

Un champ date stocké en VARCHAR. Une timezone ignorée dans un TIMESTAMP. Un DATEPART() appelé sur une chaßne de caractÚres.

Résultat : des dashboards faux. Sans message d'erreur. Sans alerte. Des KPIs qui mentent depuis des semaines.

Pourtant c'est Ă©vitable Ă  100%. Chaque format de date a un usage prĂ©cis — et les confondre coĂ»te des dĂ©cisions entiĂšres Ă  revoir.

Ce guide couvre :

  • Les 5 formats et quand les utiliser exactement

  • Les erreurs de conversion les plus courantes

  • La gestion des timezones sur PostgreSQL, BigQuery et Snowflake

  • Un prompt Claude pour auditer tes champs date en 2 minutes


đŸ§Ș Calibre ton niveau avant de commencer
Sais-tu déjà quelle est la différence entre TIMESTAMP et TIMESTAMPTZ ?
Fais le test en 5 minutes et reçois ton score instantanĂ©ment. 👉 Faire le test sur modai-lab.com/test-sql/

Résultat en direct · Niveau calibré · Parcours personnalisé_


PARTIE 1 — Les 5 formats de date et quand les utiliser


Format 1 — DATE

Ce que c'est : une date sans heure. Pas de timezone. Pas d'heure. Juste le jour.

Plage : 0001-01-01 → 9999-12-31

-- ✅ CrĂ©er une colonne DATE
CREATE TABLE events (
id INT,
date_evenement DATE -- ex: 2024-11-03
);
 
-- ✅ Usages typiques
SELECT * FROM orders WHERE date_commande = '2024-11-03';
SELECT * FROM employees WHERE date_naissance BETWEEN '1990-01-01' AND '2000-12-31';
SELECT DATE '2024-11-03' + INTERVAL '30 days'; -- calcul de date
formats-date-sql-guide-complet · 01

Quand l'utiliser :

  • Dates d'anniversaire, dates de naissance

  • Dates de commande (quand l'heure n'a pas d'importance mĂ©tier)

  • Dates de reporting (fin de mois, trimestre, exercice fiscal)

  • Dates d'Ă©chĂ©ance (factures, contrats, abonnements)

Quand NE PAS l'utiliser :

  • Logs et Ă©vĂ©nements systĂšme → TIMESTAMP

  • Interactions utilisateur avec heure prĂ©cise → DATETIME ou TIMESTAMP

  • Tout ce qui implique des fuseaux horaires diffĂ©rents → TIMESTAMPTZ


Format 2 — TIME

Ce que c'est : une heure sans date. Rarement utilisé seul en analytique.

-- ✅ Usages lĂ©gitimes (rares)
CREATE TABLE schedules (
heure_ouverture TIME, -- ex: 09:00:00
heure_fermeture TIME
);
 
-- Calculer la durée d'ouverture
SELECT heure_fermeture - heure_ouverture AS duree FROM schedules;
formats-date-sql-guide-complet · 02

Quand l'utiliser : horaires récurrents indépendants de la date (horaires d'ouverture, plannings hebdomadaires).

En pratique : trĂšs peu utilisĂ© en data analytics. Si tu as besoin d'une heure, elle est presque toujours associĂ©e Ă  une date → TIMESTAMP.


Format 3 — DATETIME / TIMESTAMP (sans timezone)

Ce que c'est : une date ET une heure, stockées telles quelles, sans information de timezone.

Attention : le nom varie selon le SGBD.

SGBD

Nom du type

Stockage

PostgreSQL

TIMESTAMP

Date + heure, pas de timezone

MySQL

DATETIME

Date + heure, pas de timezone

BigQuery

DATETIME

Date + heure civile, pas de timezone

Snowflake

TIMESTAMP_NTZ

Date + heure, no timezone

SQL Server

DATETIME2

Date + heure, pas de timezone

-- ✅ Usages typiques
CREATE TABLE blog_posts (
id INT,
published_at TIMESTAMP -- ex: 2024-11-03 14:30:00
);
 
-- Filtrer par période
SELECT * FROM blog_posts
WHERE published_at >= '2024-01-01 00:00:00'
AND published_at < '2025-01-01 00:00:00';
 
-- Tronquer à la journée
SELECT DATE_TRUNC('day', published_at) AS jour, COUNT(*) AS nb_articles
FROM blog_posts
GROUP BY ;
formats-date-sql-guide-complet · 03

Quand l'utiliser :

  • DonnĂ©es d'une seule rĂ©gion gĂ©ographique (pas de timezone ambiguĂ«)

  • Dates d'import ETL, dates de transformation

  • ÉvĂ©nements dont la timezone est dĂ©jĂ  normalisĂ©e en amont

PiĂšge classique :

-- ❌ Stocker des Ă©vĂ©nements de plusieurs pays en TIMESTAMP sans timezone
-- Un user de Paris (UTC+1) et un de New York (UTC-5) ont tous les deux
-- un login Ă  "09:00:00" → mais ce n'est pas le mĂȘme moment
 
-- ✅ Utiliser TIMESTAMPTZ pour les Ă©vĂ©nements multi-rĂ©gions
formats-date-sql-guide-complet · 04 · PiÚge classique :

Format 4 — TIMESTAMPTZ (TIMESTAMP WITH TIME ZONE)

Ce que c'est : une date, une heure ET une timezone. Le type le plus robuste pour les applications multi-pays.

SGBD

Nom du type

Comportement

PostgreSQL

TIMESTAMPTZ

Stocke en UTC, affiche en timezone locale

BigQuery

TIMESTAMP

Stocke en UTC

Snowflake

TIMESTAMP_TZ

Stocke l'offset timezone

SQL Server

DATETIMEOFFSET

Stocke avec offset

-- ✅ CrĂ©ation
CREATE TABLE user_sessions (
id INT,
started_at TIMESTAMPTZ, -- ex: 2024-11-03 14:30:00+01
ended_at TIMESTAMPTZ
);
 
-- PostgreSQL : conversion de timezone
SELECT
started_at AT TIME ZONE 'UTC' AS heure_utc,
started_at AT TIME ZONE 'Europe/Paris' AS heure_paris,
started_at AT TIME ZONE 'America/New_York' AS heure_ny
FROM user_sessions;
 
-- BigQuery : conversion de timezone
SELECT
started_at,
DATETIME(started_at, 'Europe/Paris') AS heure_paris
FROM user_sessions;
formats-date-sql-guide-complet · 05

Quand l'utiliser :

  • Applications avec des utilisateurs dans plusieurs fuseaux horaires

  • Logs serveur et Ă©vĂ©nements systĂšme

  • Toute donnĂ©e qui sera analysĂ©e dans diffĂ©rents fuseaux horaires

  • ÉvĂ©nements critiques oĂč le moment exact compte (transactions financiĂšres, audits)

💡 RĂšgle gĂ©nĂ©rale : en cas de doute, utilise TIMESTAMPTZ. Stocker en UTC et convertir Ă  l'affichage est toujours plus sĂ»r que l'inverse.


Format 5 — INTERVAL

Ce que c'est : une durée, pas un moment. La différence entre deux dates.

-- ✅ CrĂ©er des intervalles
SELECT INTERVAL '30 days';
SELECT INTERVAL '2 hours 30 minutes';
SELECT INTERVAL '1 year 3 months';
 
-- ✅ Ajouter une durĂ©e Ă  une date
SELECT '2024-01-01'::DATE + INTERVAL '30 days'; -- 2024-01-31
SELECT NOW() - INTERVAL '7 days'; -- il y a 7 jours
 
-- ✅ Calculer une durĂ©e entre deux dates
SELECT
user_id,
created_at,
first_order_at,
first_order_at - created_at AS delai_premier_achat
FROM users
JOIN (SELECT user_id, MIN(created_at) AS first_order_at FROM orders GROUP BY user_id) o
USING (user_id);
 
-- ✅ Filtrer par durĂ©e relative
SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '30 days';
SELECT * FROM users WHERE created_at BETWEEN NOW() - INTERVAL '1 year' AND NOW();
formats-date-sql-guide-complet · 06

Quand l'utiliser :

  • Calculs de dĂ©lais (temps entre inscription et premier achat)

  • Filtres relatifs ("les 30 derniers jours")

  • Calculs de durĂ©e d'abonnement, de cycle de vente


đŸ§Ș Teste tes rĂ©flexes sur les 5 formats

Les formats de date sont systématiquement testés en entretien data.

Modai Lab te soumet des cas rĂ©els avec des donnĂ©es imparfaites — score immĂ©diat.

👉 Pratiquer sur modai-lab.com
Exercices interactifs · Datasets réels · Feedback instantané


PARTIE 2 — Les erreurs de conversion les plus courantes


❌ Erreur 1 — Date stockĂ©e en VARCHAR (l'erreur la plus coĂ»teuse)

Le problĂšme

-- ❌ Colonne date stockĂ©e en texte
CREATE TABLE orders (
id INT,
order_date VARCHAR() -- ex: "2024-11-03" ou "03/11/2024" ou "Nov 3, 2024"
);
 
-- Tri faux : ordre alphabétique, pas chronologique
SELECT * FROM orders ORDER BY order_date;
-- "2024-09-01" > "2024-11-03" en VARCHAR car "9" > "1"
 
-- Calcul impossible
SELECT order_date + INTERVAL '30 days' FROM orders; -- erreur
 
-- Comparaison piégeuse
SELECT * FROM orders WHERE order_date > '2024-10-01';
-- Fonctionne par chance si le format est YYYY-MM-DD
-- Échoue silencieusement si le format est DD/MM/YYYY
formats-date-sql-guide-complet · 07 · Le problÚme

La correction

-- ✅ Migration : VARCHAR → DATE
-- Étape 1 : vĂ©rifier les formats prĂ©sents
SELECT DISTINCT
CASE
WHEN order_date ~ '^\d{4}-\d{2}-\d{2}$' THEN 'YYYY-MM-DD'
WHEN order_date ~ '^\d{2}/\d{2}/\d{4}$' THEN 'DD/MM/YYYY'
WHEN order_date ~ '^\d{2}-\d{2}-\d{4}$' THEN 'DD-MM-YYYY'
ELSE 'Format inconnu : ' || order_date
END AS format_detecte,
COUNT(*) AS n
FROM orders
GROUP BY ;
 
-- Étape 2 : convertir selon le format
ALTER TABLE orders ADD COLUMN order_date_clean DATE;
 
UPDATE orders
SET order_date_clean =
CASE
WHEN order_date ~ '^\d{4}-\d{2}-\d{2}$'
THEN TO_DATE(order_date, 'YYYY-MM-DD')
WHEN order_date ~ '^\d{2}/\d{2}/\d{4}$'
THEN TO_DATE(order_date, 'DD/MM/YYYY')
END;
 
-- Étape 3 : valider avant de supprimer l'ancienne colonne
SELECT COUNT(*) AS null_apres_conversion FROM orders WHERE order_date_clean IS NULL;
formats-date-sql-guide-complet · 08 · La correction

❌ Erreur 2 — Timezone ignorĂ©e dans les calculs

Le problĂšme

-- ❌ Comparer des timestamps de timezones diffĂ©rentes sans conversion
-- Table orders : created_at en UTC
-- Rapport : "commandes du jour" pour une équipe parisienne
 
SELECT COUNT(*) AS commandes_aujourd_hui
FROM orders
WHERE DATE(created_at) = CURRENT_DATE;
-- Si le serveur est en UTC et l'équipe est à Paris (UTC+1) :
-- Les commandes de 23h00 à 00h00 heure de Paris sont assignées au mauvais jour
formats-date-sql-guide-complet · 09 · Le problÚme
-- ✅ Toujours convertir avant de tronquer Ă  la journĂ©e
 
-- PostgreSQL
SELECT COUNT(*) AS commandes_aujourd_hui
FROM orders
WHERE DATE(created_at AT TIME ZONE 'Europe/Paris') = CURRENT_DATE;
 
-- BigQuery
SELECT COUNT(*) AS commandes_aujourd_hui
FROM orders
WHERE DATE(created_at, 'Europe/Paris') = CURRENT_DATE();
 
-- Snowflake
SELECT COUNT(*) AS commandes_aujourd_hui
FROM orders
WHERE DATE(CONVERT_TIMEZONE('UTC', 'Europe/Paris', created_at)) = CURRENT_DATE();
formats-date-sql-guide-complet · 10

L'impact concret :

-- Mesurer l'écart entre les deux approches
WITH
sans_tz AS (
SELECT DATE(created_at) AS jour, COUNT(*) AS n
FROM orders
GROUP BY
),
avec_tz AS (
SELECT DATE(created_at AT TIME ZONE 'Europe/Paris') AS jour, COUNT(*) AS n
FROM orders
GROUP BY
)
SELECT
s.jour,
s.n AS sans_conversion,
a.n AS avec_conversion_paris,
s.n - a.n AS ecart
FROM sans_tz s
JOIN avec_tz a ON s.jour = a.jour
WHERE s.n != a.n
ORDER BY s.jour;
formats-date-sql-guide-complet · 11 · L'impact concret :

❌ Erreur 3 — Conversion implicite VARCHAR → DATE

Le problĂšme

-- ❌ Comparaison qui force une conversion implicite
SELECT * FROM orders WHERE created_at = '2024-11-03';
-- created_at est TIMESTAMP, '2024-11-03' est une chaĂźne
-- Selon le SGBD, ça peut fonctionner... ou pas, ou donner un résultat faux
 
-- ❌ Fonction de date sur une chaüne de caractùres
SELECT YEAR(order_date) FROM orders;
-- Si order_date est VARCHAR, certains SGBD convertissent silencieusement
-- d'autres retournent NULL, d'autres plantent
formats-date-sql-guide-complet · 12 · Le problÚme
-- ✅ Toujours caster explicitement
SELECT * FROM orders
WHERE created_at >= '2024-11-03'::DATE
AND created_at < '2024-11-04'::DATE;
 
-- Ou avec BETWEEN sur des dates castées
SELECT * FROM orders
WHERE DATE(created_at) = '2024-11-03'::DATE;
 
-- Caster une chaĂźne en date proprement
SELECT TO_DATE('03/11/2024', 'DD/MM/YYYY') AS date_convertie; -- PostgreSQL
SELECT PARSE_DATE('%d/%m/%Y', '03/11/2024') AS date_convertie; -- BigQuery
SELECT TO_DATE('03/11/2024', 'DD/MM/YYYY') AS date_convertie; -- Snowflake
formats-date-sql-guide-complet · 13

❌ Erreur 4 — DATE_TRUNC vs EXTRACT : les confondre

Le problĂšme

-- DATE_TRUNC : tronque Ă  un niveau de granularitĂ© → retourne une date/timestamp
-- EXTRACT (ou DATE_PART) : extrait un composant → retourne un nombre
 
-- ❌ Confondre les deux dans une agrĂ©gation
SELECT EXTRACT('month' FROM created_at) AS mois, SUM(montant)
FROM orders
GROUP BY
ORDER BY ;
-- Retourne les mois 1 à 12, mais mélange TOUTES les années
-- Janvier 2023 + Janvier 2024 = un seul "mois 1"
 
-- ✅ DATE_TRUNC pour grouper par pĂ©riode sans mĂ©langer les annĂ©es
SELECT DATE_TRUNC('month', created_at) AS mois, SUM(montant)
FROM orders
GROUP BY
ORDER BY ;
-- Retourne une ligne par mois/année : 2023-01, 2023-02, ..., 2024-01
formats-date-sql-guide-complet · 14 · Le problÚme
-- Référence complÚte des fonctions par SGBD
 
-- TRONQUER À UNE PÉRIODE
-- PostgreSQL
DATE_TRUNC('year'/'month'/'week'/'day'/'hour', col)
 
-- BigQuery
DATE_TRUNC(col, YEAR/MONTH/WEEK/DAY)
TIMESTAMP_TRUNC(col, YEAR/MONTH/WEEK/DAY/HOUR)
 
-- Snowflake
DATE_TRUNC('year'/'month'/'week'/'day'/'hour', col)
 
-- EXTRAIRE UN COMPOSANT
-- PostgreSQL
EXTRACT(year/month/day/hour FROM col)
DATE_PART('year'/'month'/'day'/'hour', col)
 
-- BigQuery
EXTRACT(YEAR/MONTH/DAY/HOUR FROM col)
 
-- Snowflake
EXTRACT(year/month/day/hour FROM col)
DATE_PART('year'/'month'/'day'/'hour', col)
YEAR(col) / MONTH(col) / DAY(col)
formats-date-sql-guide-complet · 15

❌ Erreur 5 — Calcul de durĂ©e avec soustraction directe

Le problĂšme

-- ❌ Soustraction qui retourne un type inattendu selon le SGBD
SELECT created_at - first_order_at FROM users;
-- PostgreSQL : retourne un INTERVAL
-- MySQL : retourne un nombre (différence en secondes ou en jours selon les types)
-- BigQuery : retourne une erreur sur TIMESTAMP, nécessite TIMESTAMP_DIFF
 
-- ❌ Comparer des durĂ©es sans normaliser
SELECT user_id, created_at - first_order_at AS delai
FROM users
WHERE created_at - first_order_at > ;
-- "30" en quoi ? Jours ? Secondes ? Heures ?
-- Comportement non déterministe selon le SGBD
formats-date-sql-guide-complet · 16 · Le problÚme
-- ✅ Calculer des durĂ©es de façon explicite et portable
 
-- PostgreSQL : EXTRACT sur un INTERVAL
SELECT
user_id,
EXTRACT(EPOCH FROM (first_order_at - created_at)) / AS delai_jours
FROM users;
 
-- BigQuery : TIMESTAMP_DIFF ou DATE_DIFF
SELECT
user_id,
TIMESTAMP_DIFF(first_order_at, created_at, DAY) AS delai_jours
FROM users;
 
-- Snowflake : DATEDIFF
SELECT
user_id,
DATEDIFF('day', created_at, first_order_at) AS delai_jours
FROM users;
 
-- SQL Server : DATEDIFF
SELECT
user_id,
DATEDIFF(day, created_at, first_order_at) AS delai_jours
FROM users;
formats-date-sql-guide-complet · 17

PARTIE 3 — Gestion des timezones par SGBD


PostgreSQL — Le plus complet

-- Voir la timezone du serveur
SHOW timezone;
 
-- Changer de timezone pour une session
SET timezone = 'Europe/Paris';
 
-- Voir toutes les timezones disponibles
SELECT * FROM pg_timezone_names ORDER BY name;
 
-- Convertir un TIMESTAMP en TIMESTAMPTZ
SELECT '2024-11-03 14:30:00'::TIMESTAMP AT TIME ZONE 'Europe/Paris';
-- Retourne : 2024-11-03 13:30:00+00 (converti en UTC)
 
-- Convertir d'une timezone Ă  une autre
SELECT created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/New_York' AS heure_ny
FROM orders;
 
-- AT TIME ZONE sur un TIMESTAMP (sans tz) : interprÚte comme étant dans cette tz
-- AT TIME ZONE sur un TIMESTAMPTZ : convertit vers cette tz
-- Attention : deux usages diffĂ©rents du mĂȘme opĂ©rateur !
 
-- Tronquer par jour dans la timezone du user
SELECT
user_id,
DATE_TRUNC('day', created_at AT TIME ZONE user_timezone) AS jour_local,
COUNT(*) AS nb_events
FROM events e
JOIN users u ON e.user_id = u.id
GROUP BY , ;
formats-date-sql-guide-complet · 18

BigQuery — Timezone dans chaque fonction

-- BigQuery n'a pas de timezone de session
-- La timezone se spécifie dans chaque fonction
 
-- TIMESTAMP stocké en UTC, toujours
-- DATETIME = valeur civile sans timezone (à éviter pour les données globales)
 
-- Convertir un TIMESTAMP vers une timezone
SELECT
event_timestamp,
DATETIME(event_timestamp, 'Europe/Paris') AS heure_paris,
DATE(event_timestamp, 'Europe/Paris') AS date_paris
FROM events;
 
-- Tronquer par semaine dans une timezone
SELECT
TIMESTAMP_TRUNC(event_timestamp, WEEK, 'Europe/Paris') AS semaine_paris,
COUNT(*) AS nb_events
FROM events
GROUP BY ;
 
-- Créer un TIMESTAMP à partir d'une DATETIME locale
SELECT TIMESTAMP('2024-11-03 14:30:00', 'Europe/Paris') AS ts_utc;
-- Retourne : 2024-11-03 13:30:00 UTC
 
-- Différence entre deux TIMESTAMP dans une timezone
SELECT TIMESTAMP_DIFF(
TIMESTAMP('2024-11-03 18:00:00', 'Europe/Paris'),
TIMESTAMP('2024-11-03 09:00:00', 'Europe/Paris'),
HOUR
) AS heures_travaillees; -- retourne 9
formats-date-sql-guide-complet · 19

Snowflake — Trois types de TIMESTAMP

-- Snowflake a 3 types de TIMESTAMP :
-- TIMESTAMP_NTZ : pas de timezone (équivalent DATETIME)
-- TIMESTAMP_LTZ : timezone locale (session parameter)
-- TIMESTAMP_TZ : stocke l'offset timezone avec la valeur
 
-- Voir et changer la timezone de session
SHOW PARAMETERS LIKE 'TIMEZONE';
ALTER SESSION SET TIMEZONE = 'Europe/Paris';
 
-- Convertir une timezone
SELECT CONVERT_TIMEZONE('UTC', 'Europe/Paris', created_at) AS heure_paris
FROM events;
 
-- Convertir de Paris vers New York
SELECT CONVERT_TIMEZONE('Europe/Paris', 'America/New_York', created_at) AS heure_ny
FROM events;
 
-- Tronquer par jour dans une timezone
SELECT
DATE_TRUNC('day', CONVERT_TIMEZONE('Europe/Paris', created_at)) AS jour_paris,
COUNT(*) AS nb_events
FROM events
GROUP BY ;
 
-- DATEDIFF dans Snowflake
SELECT DATEDIFF('day', '2024-01-01'::DATE, '2024-12-31'::DATE) AS nb_jours;
-- Retourne : 365
formats-date-sql-guide-complet · 20

Tableau de rĂ©fĂ©rence — Les fonctions date par SGBD

Opération

PostgreSQL

BigQuery

Snowflake

Tronquer à la journée

DATE_TRUNC('day', col)

DATE_TRUNC(col, DAY)

DATE_TRUNC('day', col)

Extraire l'année

EXTRACT(year FROM col)

EXTRACT(YEAR FROM col)

YEAR(col)

Différence en jours

EXTRACT(EPOCH FROM (b-a))/86400

DATE_DIFF(b, a, DAY)

DATEDIFF('day', a, b)

Ajouter 30 jours

col + INTERVAL '30 days'

DATE_ADD(col, INTERVAL 30 DAY)

DATEADD('day', 30, col)

Convertir timezone

col AT TIME ZONE 'tz'

DATETIME(col, 'tz')

CONVERT_TIMEZONE('tz', col)

Date courante

CURRENT_DATE

CURRENT_DATE()

CURRENT_DATE()

Timestamp courant

NOW()

CURRENT_TIMESTAMP()

CURRENT_TIMESTAMP()

Cast chaüne → date

TO_DATE(col, 'fmt')

PARSE_DATE('%fmt', col)

TO_DATE(col, 'fmt')


đŸ§Ș Teste la gestion des timezones en conditions rĂ©elles

Les erreurs de timezone sont les plus difficiles Ă  dĂ©tecter — les rĂ©sultats semblent plausibles.

Modai Lab simule ces cas avec des données multi-pays et des timestamps UTC.

👉 Tester sur modai-lab.com/test-sql/

Score immédiat · Explication des erreurs · Niveau calibré


PARTIE 4 — Prompt Claude pour auditer tes champs date en 2 minutes

Copie ce prompt avec le schéma de ta table pour obtenir un audit complet.


Prompt d'audit complet

Tu es un expert SQL data quality. Audite les champs date du schéma suivant
et identifie tous les risques potentiels.
 
SCHÉMA À AUDITER :
[coller ton CREATE TABLE ou la liste de tes colonnes]
 
CONTEXTE :
- SGBD utilisé : [PostgreSQL / BigQuery / Snowflake / autre]
- Utilisateurs dans : [une seule région / plusieurs pays / global]
- Usage principal : [reporting interne / dashboard client / ETL / autre]
 
Analyse les points suivants :
 
1. TYPES DE COLONNES
- Quels champs date sont stockés en VARCHAR ou en type incorrect ?
- Quels champs devraient utiliser TIMESTAMPTZ plutĂŽt que TIMESTAMP ?
- Y a-t-il des champs durée stockés en INT ou VARCHAR ?
 
2. RISQUES TIMEZONE
- Quels champs sont à risque si les données viennent de plusieurs fuseaux ?
- Quelle timezone de référence recommandes-tu pour ce contexte ?
- Comment convertir les champs existants sans casser les données ?
 
3. CALCULS À RISQUE
- Quelles requĂȘtes sur ces champs sont susceptibles de mĂ©langer les annĂ©es ?
- Y a-t-il des risques de conversion implicite VARCHAR → DATE ?
- Comment calculer des durées de façon portable entre SGBD ?
 
4. RECOMMANDATIONS PRIORITAIRES
- Les 3 modifications les plus urgentes
- La requĂȘte de migration pour chaque modification
- Comment valider que la migration n'a pas cassé les données
 
Format : une section par point, ❌ pour les risques identifiĂ©s, ✅ pour les bonnes pratiques.
formats-date-sql-guide-complet · 21

Prompt rapide (version 30 secondes)

Audite les champs date de ce schéma SQL pour identifier :
- Les types incorrects (VARCHAR, INT Ă  la place de DATE/TIMESTAMP)
- Les risques timezone (TIMESTAMP sans tz sur données multi-pays)
- Les calculs de durée non portables
- Les recommandations prioritaires avec les requĂȘtes de migration
 
SGBD : [PostgreSQL / BigQuery / Snowflake]
Schéma : [coller]
formats-date-sql-guide-complet · 22

RequĂȘtes de diagnostic Ă  lancer sur ta base

-- PostgreSQL : inspecter les types des colonnes date
SELECT
table_name,
column_name,
data_type,
CASE
WHEN data_type IN ('character varying', 'text', 'char') THEN '⚠ Potentiellement une date stockĂ©e en texte'
WHEN data_type = 'timestamp without time zone' THEN '⚠ VĂ©rifier si timezone nĂ©cessaire'
WHEN data_type = 'timestamp with time zone' THEN '✅ Timezone gĂ©rĂ©e'
WHEN data_type = 'date' THEN '✅ Date sans heure'
WHEN data_type = 'integer' THEN '⚠ Potentiellement un timestamp Unix stockĂ© en INT'
ELSE data_type
END AS recommandation
FROM information_schema.columns
WHERE table_schema = 'public'
AND (
data_type IN ('date', 'timestamp without time zone', 'timestamp with time zone')
OR column_name ILIKE '%date%'
OR column_name ILIKE '%time%'
OR column_name ILIKE '%at'
OR column_name ILIKE '%_on'
)
ORDER BY table_name, column_name;
formats-date-sql-guide-complet · 23
-- Détecter les colonnes VARCHAR qui contiennent des dates
SELECT
column_name,
COUNT(*) AS total,
COUNT(CASE WHEN value ~ '^\d{4}-\d{2}-\d{2}' THEN END) AS format_iso,
COUNT(CASE WHEN value ~ '^\d{2}/\d{2}/\d{4}' THEN END) AS format_fr,
COUNT(CASE WHEN value ~ '^\d{2}-\d{2}-\d{4}' THEN END) AS format_eu,
COUNT(CASE WHEN value !~ '\d' THEN END) AS non_numerique
FROM (
-- Adapter avec ta colonne VARCHAR suspectée
SELECT 'order_date' AS column_name, order_date::TEXT AS value FROM orders
) t
GROUP BY column_name;
formats-date-sql-guide-complet · 24

📋 RĂ©capitulatif — Les 5 formats et leurs usages

Format

Usage

Timezone

Exemple

DATE

ÉvĂ©nements sans heure

Non

2024-11-03

TIME

Horaires récurrents

Non

09:00:00

TIMESTAMP

ÉvĂ©nements mono-rĂ©gion

Non

2024-11-03 14:30:00

TIMESTAMPTZ

ÉvĂ©nements multi-pays

Oui (UTC)

2024-11-03 13:30:00+00

INTERVAL

Durées et calculs

N/A

30 days / 2 hours


✅ Checklist d'audit de tes champs date

  • ☐ Aucun champ date n'est stockĂ© en VARCHAR ou INT

  • ☐ Les Ă©vĂ©nements multi-rĂ©gions utilisent TIMESTAMPTZ (pas TIMESTAMP)

  • ☐ Les dashboards convertissent vers la timezone locale avant de tronquer Ă  la journĂ©e

  • ☐ DATE_TRUNC est utilisĂ© pour grouper par pĂ©riode (pas EXTRACT qui mĂ©lange les annĂ©es)

  • ☐ Les calculs de durĂ©e utilisent les fonctions natives du SGBD (pas la soustraction directe)

  • ☐ Les imports de donnĂ©es valident le format date avant insertion

  • ☐ Une timezone de rĂ©fĂ©rence est documentĂ©e pour chaque table de faits


🚀 Pratiquer sur Modai Lab

Les erreurs de date ne se voient pas dans le code. Elles se voient dans les donnĂ©es — quand il est trop tard. La seule façon de les Ă©viter est de les avoir rencontrĂ©es en pratique avant.

👉 modai-lab.com/test-sql/ — Exercices SQL sur des donnĂ©es rĂ©elles avec des dates imparfaites


Guide offert suite au post LinkedIn · EntraĂźnez-vous sur modai-lab.com/test-sql/ · Partagez librement ♻