Après le dernier article sur les fonctions Window, on va maintenant faire un focus sur les dates. Pour moi, c'est un sujet indispensable à maîtriser car on s'en sert tout le temps, et c'est aussi un des endroits où on peut vite se tromper sans s'en rendre compte.
On va aller droit au but avec les fonctions qu'on utilise tout le temps : DATE_TRUNC, DATE_PART / EXTRACT, DATEADD, DATEDIFF, etc., avec des cas concrets et du SQL.
En un coup d'œil : quelle fonction pour quel besoin ?
| Besoin | Fonction Snowflake | Exemple rapide |
|---|---|---|
| Regrouper par mois, semaine, trimestre | DATE_TRUNC |
DATE_TRUNC('month', event_ts) |
| Extraire année / mois / jour | DATE_PART ou EXTRACT |
DATE_PART('year', event_ts) |
| Ajouter ou soustraire du temps | DATEADD |
DATEADD('day', 7, event_ts) |
| Calculer un écart entre 2 dates | DATEDIFF |
DATEDIFF('day', d1, d2) |
| Trouver fin de mois ou prochain lundi | LAST_DAY, NEXT_DAY |
LAST_DAY(event_ts::DATE) |
| Parser une date sans risquer une erreur | TRY_TO_DATE |
TRY_TO_DATE(val, 'DD/MM/YYYY') |
USE DATABASE demo_db;
USE SCHEMA demo;
CREATE OR REPLACE TABLE demo_events (
event_id INTEGER,
user_id INTEGER,
event_ts TIMESTAMP_LTZ,
event_type VARCHAR,
amount NUMBER(10,2)
);
INSERT INTO demo_events (event_id, user_id, event_ts, event_type, amount) VALUES
(1, 101, '2025-01-31 23:50:00'::TIMESTAMP_LTZ, 'purchase', 120),
(2, 101, '2025-02-01 00:10:00'::TIMESTAMP_LTZ, 'purchase', 80),
(3, 101, '2025-02-15 14:05:00'::TIMESTAMP_LTZ, 'refund', -20),
(4, 102, '2025-02-03 09:00:00'::TIMESTAMP_LTZ, 'purchase', 60),
(5, 102, '2025-03-01 08:30:00'::TIMESTAMP_LTZ, 'purchase', 90),
(6, 103, '2025-03-15 18:20:00'::TIMESTAMP_LTZ, 'purchase', 200);
DATE vs TIMESTAMP
Je vais peut-être rien t'apprendre, mais sur Snowflake (et ailleurs), c'est simple DATE = uniquement la date, sans heure. TIMESTAMP = date + heure, mais avec plusieurs variantes (dont TIMESTAMP_LTZ, TIMESTAMP_NTZ, TIMESTAMP_TZ).
Le point important (qu'on oublie trop souvent) c'est que avec TIMESTAMP_LTZ, Snowflake stocke en interne en UTC, mais les affichages se font dans le fuseau horaire de la session (TIMEZONE).
Donc deux sessions peuvent voir différemment la même valeur si chacune utilise un fuseau horaire différent.
ALTER SESSION SET TIMEZONE = 'UTC';
SELECT '2025-02-01 00:30:00'::TIMESTAMP_LTZ AS ts_seen_in_utc;
ALTER SESSION SET TIMEZONE = 'Europe/Paris';
SELECT '2025-02-01 00:30:00'::TIMESTAMP_LTZ AS ts_seen_in_paris;
Scénario 1 : Regrouper par mois ou semaine avec DATE_TRUNC
DATE_TRUNC sert à ramener une date ou heure au début d'une période (début du mois, du trimestre, de l'heure, etc...)
ALTER SESSION SET WEEK_START = 1; -- 1 = lundi (dimanche = 7)
SELECT
event_ts,
DATE_TRUNC('week', event_ts) AS week_start,
DATE_TRUNC('month', event_ts) AS month_start,
DATE_TRUNC('quarter', event_ts) AS quarter_start,
DATE_TRUNC('year', event_ts) AS year_start
FROM demo_events
ORDER BY event_ts;

DATE_TRUNC/!\ Attention au jour de début de semaine DATE_TRUNC('week', …)
Quand tu tronques à la semaine, le résultat dépend du paramètre de session WEEK_START et donc ce paramètre influence aussi d'autres fonctions semaine (comme DATEDIFF en weeks).
Scénario 2 : Extraire une partie d'une date (année, mois, jour...) avec DATE_PART ou EXTRACT
Quand tu veux splitter la date sur plusieurs colonnes par exemple (mois = 1..12, année, jour de semaine…), l'utilisation de DATE_PART est très pratique (ou EXTRACT, qui est une alternative).
SELECT
event_ts,
DATE_PART('year', event_ts) AS y,
DATE_PART('month', event_ts) AS m,
DATE_PART('day', event_ts) AS d
FROM demo_events;

DATE_PARTVersion EXTRACT (même idée) :
SELECT
event_ts,
EXTRACT(year FROM event_ts) AS y,
EXTRACT(month FROM event_ts) AS m,
EXTRACT(week FROM event_ts) AS w,
EXTRACT(day FROM event_ts) AS d
FROM demo_events;
week, dayofweek, yearofweek, etc.) peuvent dépendre de WEEK_START et parfois de WEEK_OF_YEAR_POLICY.
EXTRACTScénario 3 : Ajouter ou soustraire du temps avec DATEADD
DATEADD(type, value, expr) permet d'ajouter (ou soustraire si value est négatif) une quantité à une date ou heure.
Nb : Il existe des alias qui font la même chose pour du time et timestamp (TIMEADD, TIMESTAMPADD).
SELECT
event_ts,
DATEADD('day', 7, event_ts) AS plus_7_days,
DATEADD('hour', -2, event_ts) AS minus_2_hours
FROM demo_events;

DATEADDScénario 4 : Calculer un écart entre deux dates avec DATEDIFF
DATEDIFF(<type>, 'exp1', 'exp2') calcule une différence entre deux dates selon une unité (jours, heures, mois etc...).
SELECT
event_id,
user_id,
event_ts,
DATEDIFF('day',
LAG(event_ts) OVER (PARTITION BY user_id ORDER BY event_ts),
event_ts
) AS days_since_prev,
DATEDIFF('week',
LAG(event_ts) OVER (PARTITION BY user_id ORDER BY event_ts),
event_ts
) AS week_since_prev
FROM demo_events
ORDER BY user_id, event_ts;

DATEDIFFLa fonction LAG() utilisée ici est une window function. Si tu veux creuser, voir l'article Fonctions Window SQL Snowflake : OVER(), PARTITION BY, ORDER BY, ROWS.
Scénario 5 : Fin de période ou début de période (LAST_DAY, NEXT_DAY, PREVIOUS_DAY)
Dernier jour d'une période
LAST_DAY(date, part) renvoie le dernier jour de la période demandée (souvent le dernier jour du mois).
SELECT
event_ts::DATE AS d,
LAST_DAY(event_ts::DATE) AS last_day_of_month,
LAST_DAY(event_ts::DATE, 'quarter') AS last_day_of_quarter
FROM demo_events;

LAST_DAY, NEXT_DAY, PREVIOUS_DAY)Prochain lundi / précédent lundi
NEXT_DAY = renvoie le prochain jour de semaine après une date (ex : le prochain lundi).
PREVIOUS_DAY = fait l'inverse et renvoie le dernier jour de semaine avant la date (ex : le lundi précédent).
SELECT
event_ts::DATE AS d,
NEXT_DAY(event_ts::DATE, 'MONDAY') AS next_monday,
PREVIOUS_DAY(event_ts::DATE, 'MONDAY') AS prev_monday
FROM demo_events;

LAST_DAY, NEXT_DAY, PREVIOUS_DAY)Scénario 6 : Parser proprement une date ou un timestamp (TO_DATE, TO_TIMESTAMP, TRY_*)
TO_DATEprend un timestamp (ou une string au format timestamp) et supprimer l'heure.TO_TIMESTAMPconvertit vers un timestamp et mappe versTO_TIMESTAMP_NTZ/LTZ/TZselon le paramètre de sessionTIMESTAMP_TYPE_MAPPING(par défautTIMESTAMP_NTZ).- Et pour éviter de faire planter un chargement quand le format varie (ou quand une valeur est invalide), les fonctions
TRY_*(TRY_TO_DATE, TRY_TO_TIMESTAMP etc...) sont super pratiques car au lieu d'erreur, elles renvoient NULL.
SELECT
raw_value,
TO_DATE('2025.02.01 09:30:00', 'YYYY.MM.DD HH24:MI:SS') AS d,
TO_TIMESTAMP('2025.02.01 09:30:00', 'YYYY.MM.DD HH24:MI:SS') AS ts,
-- Si ça matche, OK. Sinon => NULL
TRY_TO_DATE(raw_value) AS parsed_date_default,
-- Parsing avec format explicite
TRY_TO_DATE(raw_value, 'DD/MM/YYYY') AS parsed_date_fr,
-- Timestamp : default ou avec format explicite
TRY_TO_TIMESTAMP(raw_value) AS parsed_ts_default,
TRY_TO_TIMESTAMP(raw_value, 'YYYY-MM-DD HH24:MI:SS') AS parsed_ts_fmt
FROM (
SELECT column1 AS raw_value
FROM VALUES
('2025-02-03'),
('03/02/2025'),
('2025-02-03 10:15:00'),
('not_a_date'),
(NULL)
);

TO_DATE, TO_TIMESTAMP, TRY_*)Ce type de gestion d'erreur est aussi utile dans les pipelines de chargement de données. Si tu construis des pipelines incrémentaux, voir Streams Snowflake : suivre les changements de données (CDC) qui s'appuie souvent sur des manipulations de dates.
Aller plus loin : pratiquer ces fonctions
Les fonctions de date, comme tout le SQL, ne s'apprennent vraiment qu'en pratiquant. Sur DataCertification.fr, le module SQL Lab propose 240+ exercices interactifs (du SELECT aux Window Functions) avec validation automatique dans le navigateur, dont une partie dédiée aux dates.
👉 Pratique le SQL sur DataCertification.fr
J'ai aussi regroupé tous mes articles Snowflake dans un parcours complet.
👉 Accéder à la Formation Snowflake
Tu veux que je t'accompagne sur ton projet data (Snowflake, ingestion, modélisation, performance, coûts, gouvernance) ?
👉 Réserver un appel de 30 minutes
Questions
Comment regrouper des données par mois en SQL Snowflake ?
Utilise DATE_TRUNC('month', ta_colonne_date). Cette fonction ramène n'importe quelle date au premier jour du mois. Tu peux faire pareil avec 'week', 'quarter' ou 'year' pour regrouper par semaine, trimestre ou année.
Quelle différence entre DATEADD et DATEDIFF en Snowflake ?
DATEADD ajoute ou soustrait une durée à une date. Par exemple DATEADD('day', 7, date) renvoie la date plus 7 jours. DATEDIFF calcule un écart entre deux dates dans l'unité demandée. Par exemple DATEDIFF('day', d1, d2) renvoie le nombre de jours entre d1 et d2.
Comment extraire l'année ou le mois d'une date Snowflake ?
Tu peux utiliser DATE_PART('year', date) ou EXTRACT(year FROM date). Les deux font la même chose. DATE_PART est légèrement plus courant dans les exemples Snowflake, EXTRACT est plus standard SQL. Pour le mois, remplace 'year' par 'month'.
Comment parser une date au format DD/MM/YYYY en Snowflake ?
Utilise TRY_TO_DATE(valeur, 'DD/MM/YYYY'). Si la valeur ne correspond pas au format, la fonction renvoie NULL au lieu de planter, ce qui est pratique pour les chargements de données avec formats variables.
Pourquoi DATE_TRUNC('week') donne un résultat différent selon les comptes Snowflake ?
Parce que le jour de début de semaine dépend du paramètre de session WEEK_START. Par défaut c'est 0 (dimanche) sur certains comptes. Tu peux le forcer à lundi avec ALTER SESSION SET WEEK_START = 1.
Quelle différence entre DATE et TIMESTAMP en Snowflake ?
DATE contient uniquement la date sans heure. TIMESTAMP contient la date et l'heure. Snowflake propose trois variantes de TIMESTAMP : TIMESTAMP_LTZ (avec fuseau horaire local), TIMESTAMP_NTZ (sans fuseau) et TIMESTAMP_TZ (avec fuseau horaire stocké).
Comment calculer le nombre de jours entre deux dates en Snowflake ?
Utilise DATEDIFF('day', date_debut, date_fin). Le premier paramètre est l'unité (day, week, month, year, hour, minute, second), le deuxième est la date de départ et le troisième la date de fin. Pour calculer l'écart en semaines, remplace 'day' par 'week'.
Comment ajouter ou soustraire des jours à une date en Snowflake ?"
Utilise DATEADD('day', valeur, date). Une valeur positive ajoute des jours, une valeur négative en soustrait. Par exemple DATEADD('day', -30, CURRENT_DATE()) renvoie la date d'il y a 30 jours. La même syntaxe marche avec 'month', 'year', 'hour' ou 'minute'.
Quelle différence entre TIMESTAMP_LTZ, TIMESTAMP_NTZ et TIMESTAMP_TZ en Snowflake ?
TIMESTAMP_LTZ stocke en UTC et affiche dans le fuseau horaire de la session (Local Time Zone). TIMESTAMP_NTZ ne gère pas du tout les fuseaux horaires (No Time Zone). TIMESTAMP_TZ stocke explicitement le fuseau horaire avec la valeur. Pour les applications globales, TIMESTAMP_LTZ est généralement recommandé.
Comment convertir une string en date en Snowflake ?
Utilise TO_DATE(string) si le format est standard (YYYY-MM-DD). Si le format est différent, précise-le en second argument : TO_DATE('03/02/2025', 'DD/MM/YYYY'). Pour éviter de planter sur une valeur invalide, préfère TRY_TO_DATE qui renvoie NULL au lieu de lever une erreur.
Comment obtenir le dernier jour du mois en Snowflake ?
Utilise LAST_DAY(date). La fonction renvoie le dernier jour du mois de la date passée en paramètre. Tu peux aussi passer une période en second argument pour obtenir le dernier jour du trimestre : LAST_DAY(date, 'quarter') ou de l'année : LAST_DAY(date, 'year').
Quelle différence entre TO_DATE et TRY_TO_DATE en Snowflake ?
TO_DATE lève une erreur si la valeur ne peut pas être convertie en date, ce qui fait planter la requête. TRY_TO_DATE renvoie NULL à la place. La version TRY_* est recommandée pour les chargements de données où les formats peuvent varier ou contenir des valeurs invalides, pour ne pas casser tout le pipeline sur une seule ligne mal formatée.
