Aller au contenu

%YEARS

Durée en années

Représente un nombre d'années, à ajouter à une date ou à un horodatage, ou à en retrancher.

Syntaxe

date + %YEARS(nombre)
date - %YEARS(nombre)
nombre
Le nombre d'années : une constante, une zone numérique ou une expression. Un nombre négatif fait reculer.
Résultat
Une durée, à combiner avec une date ou un horodatage par + ou -. Le jour et le mois sont conservés, sauf pour le 29 février qui devient le 28 février dans une année non bissextile.

À quoi ça sert

Garantie de deux ans, durée légale de conservation de dix ans, majorité à 18 ans : ces règles se disent en années civiles, pas en multiples de 365 jours (qui dérivent avec les années bissextiles). %YEARS tombe juste sur le même jour de l'année suivante.

Exemple 1 : Garantie, archivage, majorité

**free
// %YEARS : ajouter ou retirer des annees (garantie, majorite, archivage).
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s achat      date inz(d'2026-09-30');
dcl-s naissance  date inz(d'2010-05-15');
dcl-s controle   date inz(d'2026-09-30');
dcl-s garantie   int(10) inz(2);

// Garantie de 2 ans.
snd-msg 'Fin de garantie   : [' + %char(achat + %years(garantie) : *eur) + ']';

// Conservation comptable de 10 ans : date limite de destruction.
snd-msg 'Archivage jusqu''au : [' + %char(achat + %years(10) : *eur) + ']';

// Date de majorite, puis test par rapport a la date de controle.
snd-msg 'Majeur le          : [' + %char(naissance + %years(18) : *eur) + ']';
if controle >= naissance + %years(18);
  snd-msg 'Client majeur au controle';
else;
  snd-msg 'Client mineur au controle';
endif;

// Retrancher des annees : client recent = cree il y a moins de 3 ans.
snd-msg 'Seuil "recent"    : [' + %char(controle - %years(3) : *eur) + ']';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Fin de garantie   : [30.09.2028]
Archivage jusqu'au : [30.09.2036]
Majeur le          : [15.05.2028]
Client mineur au controle
Seuil "recent"    : [30.09.2023]

Deux ans après le 30 septembre 2026 : le 30 septembre 2028. La date de majorité est comparée au jour du contrôle directement dans le if. Retrancher des années donne un seuil, ici « client créé depuis moins de 3 ans ».

Exemple 2 : Le 29 février

**free
// %YEARS : le 29 fevrier n'existe pas toutes les annees.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s bissextile date inz(d'2028-02-29');
dcl-s i int(10);

snd-msg '29/02/2028 + 1 an  : [' + %char(bissextile + %years(1) : *eur) + ']';
snd-msg '29/02/2028 + 2 ans : [' + %char(bissextile + %years(2) : *eur) + ']';
snd-msg '29/02/2028 + 4 ans : [' + %char(bissextile + %years(4) : *eur) + ']';

// Aller-retour : on ne retombe pas sur le 29.
snd-msg 'Aller-retour       : [' + %char(bissextile + %years(1) - %years(1) : *eur) + ']';

// Anniversaire annuel en cascade : le 28 fevrier reste ensuite.
for i = 1 to 4;
  bissextile = bissextile + %years(1);
  snd-msg 'En cascade ' + %char(i) + '      : ' + %char(bissextile : *eur);
endfor;

// Retrancher : un 29 fevrier retombe aussi sur le 28.
snd-msg '29/02/2028 - 1 an  : [' + %char(d'2028-02-29' - %years(1) : *eur) + ']';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

29/02/2028 + 1 an  : [28.02.2029]
29/02/2028 + 2 ans : [28.02.2030]
29/02/2028 + 4 ans : [29.02.2032]
Aller-retour       : [28.02.2028]
En cascade 1      : 28.02.2029
En cascade 2      : 28.02.2030
En cascade 3      : 28.02.2031
En cascade 4      : 28.02.2032
29/02/2028 - 1 an  : [28.02.2027]

Le 29 février 2028 plus un an donne le 28 février 2029, plus quatre ans le 29 février 2032. Aller-retour (+1 an puis -1 an) : on retombe au 28 et non au 29. En cascade, la date reste au 28 février, même en 2032. Retrancher un an d'un 29 février donne aussi un 28.

Le piège

Le 29 février devient le 28 février dans une année non bissextile, sans erreur. Conséquence : ajouter un an à chaque étape (date = date + %YEARS(1)) fait perdre le 29 pour toujours, même en 2032. Pour un calendrier d'anniversaires, toujours partir de la date d'origine : naissance + %YEARS(n).

Comme pour les mois, + %YEARS(1) - %YEARS(1) ne ramène pas forcément à la date de départ.