> ## Content Index
> Fetch the complete content index at: https://www.idriss-benbassou.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# DATE_TRUNC, DATEDIFF, DATEADD : maîtriser les dates Snowflake
- URL: https://www.idriss-benbassou.com/dates-sql-snowflake-date-trunc-date-part-extract-dateadd-datediff/
- Published: 2026-02-05T17:30:30.000Z
- Updated: 2026-07-19T10:53:05.000Z
- Author: Idriss BENBASSOU
- Tags: Snowflake, SQL, #rating-1

Après le dernier article sur [les fonctions Window](https://www.idriss-benbassou.com/snowflake-sql-window-functions-over-partition-by-order-by-rows/), 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') |

```sql
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.

```sql
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...)

```sql
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;

```

![Regrouper par mois ou semaine avec DATE_TRUNC](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image.png)

Regrouper par mois ou semaine avec `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).

```sql
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;

```

![Extraire une partie d’une date (année, mois, jour...) avec DATE_PART ou EXTRACT](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-1.png)

Extraire une partie d'une date (année, mois, jour...) avec `DATE_PART`

Version `EXTRACT` (même idée) :

```sql
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;

```

💡

Certaines extractions liées aux semaines (`week`, `dayofweek`, `yearofweek`, etc.) peuvent dépendre de `WEEK_START` et parfois de `WEEK_OF_YEAR_POLICY`.

![Extraire une partie d’une date (année, mois, jour...) avec EXTRACT](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-2.png)

Extraire une partie d'une date (année, mois, jour...) avec `EXTRACT`

## Scé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`).

```sql
SELECT
  event_ts,
  DATEADD('day', 7, event_ts)   AS plus_7_days,
  DATEADD('hour', -2, event_ts) AS minus_2_hours
FROM demo_events;

```

![Ajouter ou soustraire du temps avec DATEADD](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-3.png)

Ajouter ou soustraire du temps avec `DATEADD`

## Scé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...).

```sql
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;

```

![Calculer un écart entre deux dates avec DATEDIFF ](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-7.png)

Calculer un écart entre deux dates avec `DATEDIFF`

La 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](https://www.idriss-benbassou.com/snowflake-sql-window-functions-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).

```sql
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;

```

![Fin de période ou début de période (LAST_DAY, NEXT_DAY, PREVIOUS_DAY)](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-10.png)

Fin de période ou début de période (`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).

```sql
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;

```

![Fin de période ou début de période (LAST_DAY, NEXT_DAY, PREVIOUS_DAY)](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-9.png)

Début de période (`LAST_DAY`, `NEXT_DAY`, `PREVIOUS_DAY`)

## Scénario 6 : Parser proprement une date ou un timestamp (TO\_DATE, TO\_TIMESTAMP, TRY\_\*)

- `TO_DATE` prend un timestamp (ou une string au format timestamp) et supprimer l'heure.
- `TO_TIMESTAMP` convertit vers un timestamp et mappe vers `TO_TIMESTAMP_NTZ/LTZ/TZ` selon le paramètre de session `TIMESTAMP_TYPE_MAPPING` (par défaut `TIMESTAMP_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.

```sql
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)
);

```

![ Parser proprement une date ou un timestamp (TO_DATE, TO_TIMESTAMP, TRY_*)](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2026/02/image-11.png)

 Parser proprement une date ou un timestamp (`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)](https://www.idriss-benbassou.com/streams-snowflake-suivre-les-changements-de-donnees-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](https://datacertification.fr/apprendre-sql?ref=idriss-benbassou.com)

J'ai aussi regroupé tous mes articles Snowflake dans un parcours complet.

👉 [Accéder à la Formation Snowflake](https://www.idriss-benbassou.com/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](https://calendly.com/idriss-benbassou-datavio/30min?ref=idriss-benbassou.com)

## 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.