PerroCobolero

PerroCobolero

ADS

miércoles, 27 de julio de 2016

Fechas: Juliana, Gregoriana, DB2...

Fechas: Juliana, Gregoriana, DB2...



Para aquellos que habéis estado en más de un proyecto, seguro que os ha pasado que en cada sitio almacenan las fechas de una manera distinta. En este artículo vamos a ver las formas más comunes de almacenar fechas y como pasarlas de uno a otro formato.

Fecha DB2
Es aquella que tiene formato "DATE" en la correspondiente tabla.
Su definición sería: AAAA-MM-DD

Ejemplos
COBOL: 01  WX-FECHA-DB2 PIC X(10) VALUE '2011-01-01'.
PL/I : DCL WX_FECHA_DB2 CHAR(10)  INIT ('2011-01-01');


Fecha Juliana
En tabla se tendría formato DECIMAL (7), pues se trata de un número de 7 dígitos. La información que almacena es el año de 4 dígitos, y el día del año entre 1 y 365. Su definición sería: AAAADDD

Ejemplos
COBOL: 01  WX-FECHA-JUL PIC 9(7)   VALUE 2011001.
PL/I : DCL WX_FECHA_JUL PIC '(7)9' INIT (2011001);


Fecha gregoriana
En tabla tendría formato DECIMAL (8), pues se trata de un número de 8 dígitos. La información que se almacena es el año de 4 dígitos, el mes y el día del mes.
Su definición sería: AAAAMMDD

Ejemplos
COBOL: 01  WX-FECHA-GREG PIC 9(8)   VALUE 20110101.
PL/I : DCL WX_FECHA_GREG PIC '(8)9' INIT (20110101);


Pero a la hora de mostrar una fecha por pantalla, no se usa ninguno de esos formatos, sino el más entendible por el usuario: el mítico DD-MM-AAAA (01-01-2011).
Ya sea con guiones o con barras, la transformación a este formato suele ser común en los programas online.
Vamos a ver como transformaríamos cada uno de los formatos anteriores al formato de pantalla.

De AAAA-MM-DD a DD-MM-AAAA
(...)
WORKING-STORAGE SECTION.
01 WX-FECHA-DB2.
   05 WX-AAAA-DB2    PIC 9(4).
   05 FILLER         PIC X.
   05 WX-MM-DB2      PIC 9(2).
   05 FILLER         PIC X.
   05 WX-DD-DB2      PIC 9(2).

01 WX-FECHA-ONLINE.
   05 WX-DD-ONLINE   PIC 9(2).
   05 FILLER         PIC X VALUE '-'.
   05 WX-MM-ONLINE   PIC 9(2).
   05 FILLER         PIC X VALUE '-'.
   05 WX-AAAA-ONLINE PIC 9(4).

PROCEDURE DIVISION.
 

     MOVE '1999-31-12' TO WX-FECHA-DB2

     MOVE WX-AAAA-DB2  TO WX-AAAA-ONLINE
     MOVE WX-MM-DB2    TO WX-MM-ONLINE
     MOVE WX-DD-DB2    TO WX-DD-ONLINE

     DISPLAY 'FECHA ONLINE:' WX-FECHA-ONLINE

     STOP RUN
     .



Como veis este cambio no tiene mucha ciencia^^

De AAAAMMDD a DD-MM-AAAA
(...)
WORKING-STORAGE SECTION.
01 WX-FECHA-GREG.
   05 WX-AAAA-8      PIC 9(4).
   05 WX-MM-8        PIC 9(2).
   05 WX-DD-8        PIC 9(2).

01 WX-FECHA-ONLINE.
   05 WX-DD-ONLINE   PIC 9(2).
   05 FILLER         PIC VALUE '-'.
   05 WX-MM-ONLINE   PIC 9(2).
   05 FILLER         PIC VALUE '-'.
   05 WX-AAAA-ONLINE PIC 9(4).

PROCEDURE DIVISION.

     MOVE 19991231  TO WX-FECHA-8
 
     MOVE WX-AAAA-8 TO WX-AAAA-ONLINE
     MOVE WX-MM-8   TO WX-MM-ONLINE
     MOVE WX-DD-8   TO WX-DD-ONLINE

     DISPLAY 'FECHA ONLINE:' WX-FECHA-ONLINE

     STOP RUN
     .


Veis que es prácticamente lo mismo que en el caso anterior.

También puede ser necesario transformar las fechas entre el formato juliano y el gregoriano:

De AAAAMMDD a AAAADDD
(...)
WORKING-STORAGE SECTION.
01 WX-FECHA-JUL.
   05 WX-AAAA-JUL PIC 9(4).
   05 WX-DDD-JUL  PIC 9(3).

01 WX-FECHA-GREG.
   05 WX-AAAA-8   PIC 9(4).
   05 WX-MM-8     PIC 9(2).
   05 WX-DD-8     PIC 9(2).

PROCEDURE DIVISION.

     MOVE 20111231  TO WX-FECHA-GREG

     MOVE WX-AAAA-8 TO WX-AAAAA-JUL
     MOVE WX-DD-8   TO WX-DD-JUL

     IF WX-MM-8 EQUAL 12
        ADD 30      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 11
        ADD 31      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 10
        ADD 30      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 9
        ADD 31      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 8
        ADD 31      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 7
        ADD 30      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 6
        ADD 31      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 5
        ADD 30      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 4
        ADD 31      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     IF WX-MM-8 EQUAL 3
        ADD 28      TO WX-DD-JUL
        SUBSTRACT FROM WX-MM-8
     END-IF

     DIVIDE WX-AAAA-8 BY GIVING WX-AAAA-8 REMAINDER WX-RESTO

     IF WX-RESTO EQUAL ZEROES
        ADD 1       TO WX-DDD-JUL
     END-IF

     IF WX-MM-8 EQUAL 2
        ADD 31      TO WX-DD-JUL
     END-IF

     DISPLAY 'FECHA JULIANA (YYYYDDD):' WX-FECHA-JUL

     STOP RUN
     .



Aquí ya se complica un poco la cosa. Normalmente suelen existir rutinas generales para hacer este formateo. Por ejemplo, una rutina que recibe la fecha en formato AAAAMMDD por linkage y la devuelve en formato AAAADDD.

De AAAADDD a AAAAMMDD
(...)
WORKING-STORAGE SECTION.
01 TABLA-MM-DD.
   05 MM-01       PIC 9(3) COMP-3 VALUE 0.
   05 MM-02       PIC 9(3) COMP-3 VALUE 31.
   05 MM-03       PIC 9(3) COMP-3 VALUE 59.
   05 MM-04       PIC 9(3) COMP-3 VALUE 90.
   05 MM-05       PIC 9(3) COMP-3 VALUE 120.
   05 MM-06       PIC 9(3) COMP-3 VALUE 151.
   05 MM-07       PIC 9(3) COMP-3 VALUE 181.
   05 MM-08       PIC 9(3) COMP-3 VALUE 212.
   05 MM-09       PIC 9(3) COMP-3 VALUE 243.
   05 MM-10       PIC 9(3) COMP-3 VALUE 273.
   05 MM-11       PIC 9(3) COMP-3 VALUE 304.
   05 MM-12       PIC 9(3) COMP-3 VALUE 334.

01 TABLA-MM-DD-R REDEFINES TABLA-MM-DD.
   05 MM-DIAS OCCURS 12 TIMES 
                  PIC 9(3) COMP-3.
01 WX-ANO-BIS     PIC S9(3) COMP-3.
   88 ANO-BIS-SI                  VALUE 0.
01 WX-FIL9        PIC S9(3) COMP-3.
01 WX-FECHA-JUL.
   05 WX-AAAA-JUL PIC 9(4).
   05 WX-DDD-JUL  PIC 9(3). 

01 WX-FECHA-GREG.
   05 WX-AAAA-8   PIC 9(4).
   05 WX-MM-8     PIC 9(2).
   05 WX-DD-8     PIC 9(2).

PROCEDURE DIVISION.
     DISPLAY 'FECHA JULIANA: 2011059'

     MOVE 2011059     TO WX-FECHA-JUL
     MOVE WX-AAAA-JUL TO WX-AAAA-8 


*--- COMPROBAR AÑO BISIESTO: RESTO = 0 = AÑO BISIESTO
     DIVIDE WX-AAAA-JUL BY GIVING WX-FIL9 REMAINDER WX-ANO-BIS

*--- CORREGIR VALORES MM-DD PARA AÑO BISIESTO
     IF ANO-BIS-SI
        ADD TO MM-03
                 MM-04
                 MM-05
                 MM-06
                 MM-07
                 MM-08
                 MM-09
                 MM-10
                 MM-11
                 MM-12
     END-IF

*--- DETERMINA EN QUE MES ESTAMOS
     PERFORM VARYING WX-MM-8 FROM 12 BY -1
        UNTIL MM-DIAS(WX-MM-8) < WX-DDD-JUL 

     END-PERFORM 

*--- EL RESTO DE DDD SON LOS DIAS DENTRO DEL MES 
     SUBTRACT MM-DIAS(WX-MM-8) FROM WX-DDD-JUL GIVING WX-DD-8 

     DISPLAY 'FECHA AAAAMMDD:' WX-FECHA-GREG 

     STOP RUN 
     .



Por supuesto puede haber otras maneras de hacer estos cambios. Existen también funciones intrínsecas de COBOL que hacen la transformación, pero normalmente no dejan usarlas porque consumen muchos recursos.

No hay comentarios.:

Publicar un comentario