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 X VALUE '-'.
05 WX-MM-ONLINE PIC 9(2).
05 FILLER PIC X 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 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 11
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 10
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 9
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 8
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 7
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 6
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 5
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 4
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 3
ADD 28 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
DIVIDE WX-AAAA-8 BY 4 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 4 GIVING WX-FIL9 REMAINDER WX-ANO-BIS
*--- CORREGIR VALORES MM-DD PARA AÑO BISIESTO
IF ANO-BIS-SI
ADD 1 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.
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 X VALUE '-'.
05 WX-MM-ONLINE PIC 9(2).
05 FILLER PIC X 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 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 11
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 10
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 9
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 8
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 7
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 6
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 5
ADD 30 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 4
ADD 31 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
IF WX-MM-8 EQUAL 3
ADD 28 TO WX-DD-JUL
SUBSTRACT 1 FROM WX-MM-8
END-IF
DIVIDE WX-AAAA-8 BY 4 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 4 GIVING WX-FIL9 REMAINDER WX-ANO-BIS
*--- CORREGIR VALORES MM-DD PARA AÑO BISIESTO
IF ANO-BIS-SI
ADD 1 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