RPG-IV reconnait les variables date/heure depuis la V3R10. SDD SQL RPG-IV type de donnée : | L = date | DATE | D | | T = heure | TIME | T | | Z = timestamp | TIMESTAMP | Z | les dates peuvent avoir un des formats suivants : format lg présentation séparateur *YMD 8 40/01/01 à 39/12/31 au choix '.' '/' '-' '&'=blanc *DMY 8 01/01/40 à 31/12/39 - idem - *MDY 8 01/01/40 à 12/31/39 - idem - *JUL 6 40/001 à 39/365 - idem - *JOB ? DSPF uniquement -> *DMY à l'écran / *ISO dans le programme ou un format normalisé : *ISO 10 yyyy-mm-dd (format par dft) imposé '-' *USA 10 mm/dd/yyyy " '/' *EUR 10 dd.mm.yyyy " '.' *JIS 10 yyyy-mm-dd " '-' (standard Japonais) |
Une variable de type heure accepte les formats suivants : format lg présentation séparateur *HMS 8 00:00:00 à 24:00:00 au choix '.' '/' '-' '&'=blanc *ISO 8 00.00.00 à 24.00.00 imposé '.' *USA 8 00:00 AM à 12:00 AM imposé ':' *EUR 8 00.00.00 à 24.00.00 imposé '.' *JIS 8 00:00:00 à 24:00:00 imposé ':' Les variables horodatage n'ont qu'un seul format : yyyy-mm-dd-hh.mm.ss.uuuuuu <--date--><-heure-><micro- secondes> ces variables date sont stockées physiquement(format interne) sous la forme: - date = 4 octets - heure = 3 octets ce qui permet toutes formes - horodatage = 10 octets de comparaisons. mais nous les voyons TOUJOURS (DSPPFM,RPG IV, DUMP) sous le format externe d'une "date éditée" (en clair, avec les séparateurs) |
Ces paramètres peuvent être indiqués : sur une spécif I niveau zone 31-34 = format 35 = séparateur quand la position 36 (type), contient D,T ou Z. sur une spécif O niveau zone 53-80 = format[séparateur] Pour un fichier externe ces infos sont reprises de la définition SDD. Sinon, le système recherche: ! sur la définition (spécif I, O ou D) ! sur la spécif F (mot-clé DATFMT,TIMFMT) ! sur la spécif H ( - idem - ) V *ISO par défaut. Les mots-clés DATFMT, TIMFMT ont la syntaxe suivante: DATFMT(format[séparateur]) TIMFMT(format[séparateur]) [séparateur] n'est admis que pour les formats ayant un séparateur au choix. exemples : DATFMT(*EUR) - DATFMT(*DMY/) - TIMFMT(*ISO) |
Ne pas confondre DATFMT = format des variables date par défaut et DATEDIT = format de UDATE(6dt 0) et *DATE(8dt 0). Toute constante peut être précédée de T' ', D' ', Z' ' . Exemple : DWDATE S D DATFMT(*DMY/) puis v-------------------[format specif H] C move D'1995-07-15' wdate ou DWDATISO S D DATFMT(*ISO) D INZ(D'1995-07-15') ou encore Ddsdate DS D cejour D DATFMT(*ISO) INZ D an 4 0OVERLAY(cejour) D mois 2 0OVERLAY(cejour:6) D jour 2 0OVERLAY(cejour:9) C move *YEAR an C move *MONTH mois C move *DAY jour |
manipulation : Toute comparaison de dates entre elles, heures entre elles est cohérente indépendamment du format ! La conversion est assurée par MOVE,MOVEL ou %DATE,%DEC en /free . date <-> date, etc..., changement de format transparent. numérique,caractère <-> Date numérique,caractère <-> heure numérique,caractère <-> horodatage le facteur 1 permet alors de préciser le format de l'élément numérique ou caractère. (*ISO, *EUR , *YMD , *DMY etc... plus *CYMD ou *JOBRUN) Exemple : DNUMDAT S 8 0 INZ(19950715) DWDATEUR S D DATFMT(*EUR) C *ISO move numdat wdateur |
Pour les variables alpha, il est possible d'indiquer le séparateur dans le format (facteur 1 ou paramètre de %DATE ) : *fmtX avec fmt pour le format et X pour le séparateur & pour un espace 0 pour indiquer l'absence de séparateur *ymd/ indique une variable alpha de 8 c contenant AA/MM/JJ *ymd. " " " " " AA.MM.JJ *ymd& " " " " " AA MM JJ *ymd0 " " " " de 6 c " AAMMJJ /free // exemple valide à partir de la V5R10 : datchar = '17092001' ; datcmd = %DATE(datchar : *EUR0) ; //*EUR avec le chiffre 0 /end-free |
le code opération TIME (historique) est modifié : TIME avec une zone résultat de 12 ==> HHMMSSAAMMJJ 14 ==> HHMMSSAAAAMMJJ date ==> date en cours heure ==> l'heure en cours horodatage ==> l'horloge système En /free, utilisez %DATE(), %TIME(), %TIMESTP() [sans argument] Le nouveau code opération TEST, permet de tester la validité. TEST(D|T|Z) - la zone résultat est une variable numérique ou charactère - il faut indiquer un format en facteur 1 (comme le MOVE) et soit un indicateur (pos <<), soit (E) et tester: if %error. Exemple : C *YMD TEST(D E) datchar |
Notion de durée (avant la V5R10) : le code opération ADDDUR permet d'ajouter une durée à une date (le résultat est une date) Le code opération SUBDUR permet 1/ de soustraire une durée à une date (le résultat est une date) 2/ de soustraire une date à une date (le résultat est une durée) Une durée est un entier numérique (constante ou variable [15 maxi]) suivi d'un code (séparé par :), représentant la signification : *YEARS ou *Y : la durée est exprimée en nbr d'années *MONTHS ou *M nbr de mois *DAYS ou *D nbr de jours *HOURS ou *H nbr d'heures *MINUTES ou *MN nbr de minutes *SECONDS ou *S nbr de secondes *MSECONDS ou *MS nbr de microsecondes |
la version 5.10 permet de calculer avec des dates/heures en format libre : date2 = date1 + durée ; date3 = date2 - durée ; la fonction %DIFF() permet d'obtenir un écart la représentation des durées est alors réalisée à l'aide des fonctions intégrées du RPG : %DAYS(x) pour ajouter/retrancher x jours %MONTHS(x) pour ajouter/retrancher x mois %YEARS(x) pour ajouter/retrancher x années %HOURS(x) pour ajouter/retrancher x heures %MINUTES(x) pour ajouter/retrancher x minutes %SECONDS(x) pour ajouter/retrancher x secondes %MSECONDS(x) pour ajouter/retrancher x micro-secondes |
Exemples: dat2 = dat1 + 12 mois C DAT1 ADDDUR 12:*M DAT2 dat2 = dat2 + 45 jours C eval nbj = 45 C ADDDUR nbj:*D DAT2 dat2 = dat1 - 3 mois C DAT1 SUBDUR 3:*M DAT2 nbm = nombre de mois d'écart entre dat1 et dat2 C DAT1 SUBDUR DAT2 nbm:*M ATTENTION ! Vous ne pouvez pas tester "IF nbm > 3", le système considère qu'il y a 3 mois d'écart entre 15/07/95 et 31/10/95 (le nombre de mois est une information qui ne tient pas compte des jours) Pour tester que dat2 n'est pas > de plus de 3 mois à dat1, écrivez : C DAT1 ADDDUR 3:*M DATMAX C IF dat2 > datmax |
Exemples (V5R10) : /free // dat2 = dat1 + 12 mois DAT2 = DAT1 + %MONTHS(12) ; // dat2 = dat2 + 45 jours nbj = 45 ; DAT2 += %DAYS(nbj) ; // dat2 = dat1 - 3 mois DAT2 = DAT1 - %MONTHS(3) ; // nbm = nombre de mois d'écart entre dat1 et dat2 nbm = %DIFF(dat1 : dat2 : *M) ; // Pour tester que dat2 n'est pas > de plus de 3 mois à dat1, écrivez : if dat2 > dat1 + %MONTHS(3); /end-free |
Il est possible de calculer l'écart (la durée) entre : une date et un horodatage , une heure et un horodatage Une durée peut être négative. Le résultat d'une différence peut être négatif (si dat1 < à dat2) Ajouter -90 jours (= soustraire 90 jours, qui l'eut cru ?) Ajouter un nombre de jours va impacter la partie mois (et peut-être année) Ajouter un nombre de mois va peut-être modifier l'année, en aucun cas le jour. ( sauf fin de mois : 31/01 + 1 mois = 28/02 ou 29/02 ) Modifier la partie heure d'un horodatage, peut impacter la partie date. Il n'y a pas de fonction pour retrouver le dernier jour du mois mais le changement de mois lors d'un ajout de jours est cohérent. |
Il est enfin possible d'extraire une partie d'une date/heure/horodatage. avec EXTRCT ou %SUBDT( en V5R10) : C EXTRCT DAT2:*M mois Le facteur 2 contient la variable date/heure suivi du code, indiquant la partie à extraire (séparé par :) (ici mois contient le n° de mois de DAT2) /free // exemple V5R10 : // la variable résultat doit être numérique 2 OU 4 chiffres. // (on retourne toujours l'année sur 4) mois = %SUBDT(DAT2 : *M) ; // fin de mois du 26 Mars = 26 Avril - 26 jours findemois = DAT1 + %MONTH(1) - %DAYS( %SUBDT(DAT1+%MONTH(1)):*DAYS)) /end-free |
Quelques nouveautés version 7.2 en ce qui concerne les dates la précision d'un TimeSTamp peut être indiqué lors de la déclaration entre 0 et 12 (en version précédente, c'était forcément 6) DCL-S tstp timestamp(12); la fonction %SECONDS, utilisée dans un calcul admet un argument avec décimales : %SECONDS(1,5) la fonction %DIFF admet un 4ème argument indiquant les millisecondes %DIFF(ts1:ts2:*SECONDS:5) la fonction %SUBDT admet aussi la précision à extraire %SUBDT(Z'2014-07-21-15.20.26.123456789012':*SECONDS:10:8) -> extrait 26,12345678 |