En el post de hoy queremos compartir una curiosidad que hemos encontrado trabajando con campos de tipo fecha en Oracle. ¡¡¡¡Hay varios días que no existen en la BBDD!!!!
Esto se debe al cambio de calendario que se produjo en 1582. Hasta entonces, desde el año 46 aC, se usaba el calendario juliano, instaurado por Julio César. En ese año se instauró el calendario que actualmente usamos, el calendario gregoriano, promovido por el Papa Gregorio XIII. En esa transición se perdieron 10 días, desde el 5 de Octubre de 1582 hasta el 14 de Octubre de 1582.
Podemos comprobarlo en Oracle de la siguiente manera:
SQL> select to_date(’12/10/1582′,’dd/mm/yyyy’) from dual;
TO_DATE(
——–
15/10/82
La BBDD Oracle ignora estos días que no existen y toma como día real el primer día hábil después de ellos, el 15 de octubre de 1582, pero no devuelve un error al referirse a ellos. En cambio, si se busca un día “que sí existe”, se muestra correctamente.
SQL> select to_date(’01/10/1582′,’dd/mm/yyyy’) from dual;
TO_DATE(
——–
01/10/82
Los días que no existen se pueden comprobar con un sencillo programa en PL/SQL, comparando con los días en el calendario Juliano, que sí que existen.
SQL> set serveroutput on
SQL> DECLARE
2 fecha_inicio DATE := to_date(’01/10/1582′,’dd/mm/yyyy’);
3 fecha_fin DATE := to_date(’20/10/1582′,’dd/mm/yyyy’);
4 fecha DATE;
5 BEGIN
6 dbms_output.put_line(‘Fecha inicio: ‘ || to_char(fecha_inicio,’dd/mm/yyyy’));
7 dbms_output.put_line(‘Fecha inicio Juliano: ‘ || to_char(fecha_inicio,’j’));
8 dbms_output.put_line(‘Fecha fin: ‘ || to_char(fecha_fin,’dd/mm/yyyy’));
9 dbms_output.put_line(‘Fecha fin Juliano: ‘ || to_char(fecha_fin,’j’));
10 FOR i IN to_char(fecha_inicio,’j’)..to_char(fecha_fin,’j’) LOOP
11 select to_date(i,’j’) Into fecha from dual;
12 dbms_output.put_line(to_char(fecha,’dd/mm/yyyy’) || ‘ ‘ || to_char(fecha,’j’));
13 END LOOP;
14 END;
15 /
Fecha inicio: 01/10/1582
Fecha inicio Juliano: 2299157
Fecha fin: 20/10/1582
Fecha fin Juliano: 2299166
01/10/1582 2299157
02/10/1582 2299158
03/10/1582 2299159
04/10/1582 2299160
15/10/1582 2299161
16/10/1582 2299162
17/10/1582 2299163
18/10/1582 2299164
19/10/1582 2299165
20/10/1582 2299166
Procedimiento PL/SQL terminado correctamente.
Se puede comprobar qué ocurre cuando se intenta utilizar una de las fechas que no existen, por ejemplo en una operación de INSERT.
SQL> CREATE TABLE prueba_fechas (fecha DATE);
Tabla creada.
SQL> INSERT INTO prueba_fechas VALUES (to_date(’12/10/1582′,’dd/mm/yyyy’));
1 fila creada.
SQL> SELECT * FROM prueba_fechas;
FECHA
——–
15/10/82
Deseamos que este post os haya sido de utilidad.
Nos vemos en próximos posts,
Equipo de Base de datos
Fuentes:
CCC 11g Release 1 (11.1) (https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1838)
Calendario gregoriano. Wikipedia, La enciclopedia libre. Desde https://es.wikipedia.org/wiki/Calendario_gregoriano
Calendario juliano. Wikipedia, La enciclopedia libre. Desde https://es.wikipedia.org/wiki/Calendario_juliano