Catégories :

Fonctions de date et d’heure

MONTHS_BETWEEN

Renvoie le nombre de mois entre deux valeurs DATE ou TIMESTAMP.

Par exemple, MONTHS_BETWEEN('2020-02-01'::DATE, '2020-01-01'::DATE) renvoie 1.0.

Voir aussi :

DATEDIFF

Syntaxe

MONTHS_BETWEEN( <date_expr1> , <date_expr2> )

Arguments

expr_date1

La date à partir de laquelle soustraire.

expr_date2

La date vers laquelle soustraire.

Renvoie

Un FLOAT représentant le nombre de mois entre les deux dates.

Le nombre est calculé comme décrit ci-dessous :

  • La partie entière du FLOAT est calculée en utilisant les parties année et mois des valeurs d’entrée.

  • Dans la plupart des cas, la partie fractionnaire est calculée en utilisant les parties jour et heure des valeurs d’entrée. (Lors du calcul de la fraction de mois, la fonction considère que chaque mois compte 31 jours).

    Il y a toutefois deux exceptions :

    • Si les jours du mois sont les mêmes (par exemple 28 février et 28 mars), la partie fractionnaire est égale à zéro, même si une ou les deux valeurs saisies sont des horodatages et que les heures diffèrent.

    • Si les jours du mois sont tous les deux le dernier jour du mois (par exemple 28 février et 31 mars), la partie fractionnaire est égale à zéro, même si les dates du mois ne sont pas les mêmes.

    Par exemple, la fonction considère que chacune des paires de dates/heures suivantes est espacée d’exactement 1.0 mois :

    Date/horodatage 1

    Date/horodatage 2

    Remarques

    2019-03-01 02:00:00

    2019-02-01 13:00:00

    Le même jour de chaque mois.

    2019-03-28

    2019-02-28

    Le même jour de chaque mois.

    2019-03-31

    2019-02-28

    Le dernier jour de chaque mois.

    2019-03-31 01:00:00

    2019-02-28 13:00:00

    Le dernier jour de chaque mois.

Notes sur l’utilisation

  • Si la date (ou l’horodatage) d1 représente un moment antérieur à d2, alors MONTHS_BETWEEN(d1, d2) renvoie une valeur négative ; sinon, il renvoie une valeur positive. Plus généralement, l’échange des entrées inverse le signe : MONTHS_BETWEEN(d1, d2) = -MONTHS_BETWEEN(d2, d1).

  • Vous pouvez utiliser une valeur DATE pour un paramètre d’entrée et une valeur TIMESTAMP pour l’autre.

  • Si vous utilisez une ou plusieurs valeurs TIMESTAMP mais que vous ne voulez pas de différences fractionnaires en fonction de l’heure de la journée, alors convertissez vos expressions TIMESTAMP en DATE.

  • Si vous ne voulez que des valeurs entières, vous pouvez tronquer, arrondir ou convertir la valeur. Par exemple :

    SELECT
        ROUND(MONTHS_BETWEEN('2019-03-31 12:00:00'::TIMESTAMP,
                             '2019-02-28 00:00:00'::TIMESTAMP)) AS MonthsBetween1;
    +----------------+
    | MONTHSBETWEEN1 |
    |----------------|
    |              1 |
    +----------------+
    
  • Si une entrée est NULL, le résultat est NULL.

Exemples

Cet exemple montre les différences en mois entiers. La première paire de dates a le même jour du mois (le 15). La deuxième paire de dates correspond aux derniers jours de leurs mois respectifs (28 février et 31 mars).

SELECT
    MONTHS_BETWEEN('2019-03-15'::DATE,
                   '2019-02-15'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-31'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween2;
+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 |
|----------------+----------------|
|       1.000000 |       1.000000 |
+----------------+----------------+

L’exemple suivant montre les différences entre les mois fractionnés.

  • Pour la première colonne, la fonction obtient deux dates.

  • Pour la deuxième colonne, la fonction obtient deux horodatages qui représentent les deux mêmes dates que celles utilisées pour la première colonne, mais avec des heures différentes. La différence dans la deuxième colonne est plus importante que dans la première en raison des différences de temps.

  • Pour la troisième colonne, la fonction a obtenu deux horodatages qui représentent le même jour de leurs mois respectifs. La fonction ignore donc tout écart entre les horodatages, de sorte que la partie fractionnaire est 0.

SELECT
    MONTHS_BETWEEN('2019-03-01'::DATE,
                   '2019-02-15'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-01 02:00:00'::TIMESTAMP,
                   '2019-02-15 01:00:00'::TIMESTAMP) AS MonthsBetween2,
    MONTHS_BETWEEN('2019-02-15 02:00:00'::TIMESTAMP,
                   '2019-02-15 01:00:00'::TIMESTAMP) AS MonthsBetween3
    ;
+----------------+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 | MONTHSBETWEEN3 |
|----------------+----------------+----------------|
|       0.548387 |       0.549731 |       0.000000 |
+----------------+----------------+----------------+

La fonction renvoie un nombre entier de mois aussi bien lorsque les jours du mois sont les mêmes (par exemple 28 février et 28 mars) que lorsque les jours du mois sont le dernier jour du mois (par exemple 28 février et 31 mars). Cela peut conduire à un comportement contre-intuitif ; plus précisément, avancer la première date de la paire n’augmente pas toujours la valeur de sortie. Dans cet exemple, comme la première date avance du 28 au 30, puis au 31 mars, la différence augmente de 1.0 à un nombre plus élevé puis diminue à nouveau à 1.0.

  • Pour la première colonne, les dates d’entrée représentent le même jour dans différents mois, de sorte que la fonction renvoie 0 pour la partie fractionnaire du résultat.

  • Pour la deuxième colonne, les dates d’entrée représentent différents jours dans différents mois (et ne sont pas toutes deux le dernier jour du mois), de sorte que la fonction calcule la partie fractionnaire du résultat.

  • Pour la troisième colonne, les dates d’entrée représentent les derniers jours de deux mois différents, de sorte que la fonction renvoie à nouveau 0 pour la partie fractionnaire du résultat.

SELECT
    MONTHS_BETWEEN('2019-03-28'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-30'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween2,
    MONTHS_BETWEEN('2019-03-31'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween3
    ;
+----------------+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 | MONTHSBETWEEN3 |
|----------------+----------------+----------------|
|       1.000000 |       1.064516 |       1.000000 |
+----------------+----------------+----------------+

Cet exemple montre que l’inversion de l’ordre des paramètres inverse le signe du résultat :

SELECT
    MONTHS_BETWEEN('2019-03-01'::DATE,
                   '2019-02-01'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-02-01'::DATE,
                   '2019-03-01'::DATE) AS MonthsBetween2
    ;
+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 |
|----------------+----------------|
|       1.000000 |      -1.000000 |
+----------------+----------------+