Manipulando fechas con Horas en PL/SQL y SQL

La manera correcta de jugar con fechas en Oracle es truncando, sumando y restando. La manipulacion de cadenas puede ser una hábito muy peligroso que ni me molestaré en comentar.

Supongamos que tengo dos fechas (15/2/2007, 28/2/2007 10:12) y quiero que una herede la hora de la otra (15/2/2007 10:12). Vayamos paso a paso:

Select To_date ('15/2/2007 00:00:00', 'DD/MM/YYYY HH24:MI:SS'),
To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS')
From DUAL;

Como primer paso me quedo con la parte “día entero” de la hora. Es decir las 00:00.00 de ese día con la función TRUNC. La función trunc tiene otros usos mucho más vistosos si empleamos un segundo parámetro de máscara.

Select TRUNC (To_date ('15/2/2007 00:00:00', 'DD/MM/YYYY HH24:MI:SS'))
From DUAL;

Internamente Oracle almacena las fechas como un número. Luego si resto dos fecha recibo un número. Este representa una fracción de día, siendo 1 un día completo.

Select To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS')
- TRUNC (To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS'))
From DUAL;

El resultado es la suma de los anteriores resultados.

Select TRUNC (To_date ('15/2/2007 00:00:00', 'DD/MM/YYYY HH24:MI:SS'))
+ ( To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS')
- TRUNC (To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS')))
From DUAL;

Quizá queda un poco confuso pero veamos como queda como llamada anónima PL/SQL.

Declare
fecha_sin_hora Date := To_date ('15/2/2007 00:00:00', 'DD/MM/YYYY HH24:MI:SS');
fecha_con_hora Date := To_date ('28/2/2007 10:12', 'DD/MM/YYYY HH24:MI:SS');
fecha_resultado Date;
resto_hora Number;
Begin
fecha_resultado := TRUNC (fecha_sin_hora);
-- convierte a solo dia por si hubiese algun resto de hora
resto_hora := fecha_con_hora - TRUNC (fecha_con_hora);
-- es un numero, concretamente una fraccion de hora
fecha_resultado := TRUNC (fecha_sin_hora) + resto_hora;
-- el resultado sera la suma de la parte entera mas el numero fraccion de dia.
DBMS_OUTPUT.put_line (TO_CHAR (fecha_resultado, 'DD/MM/YYYY HH24:MI:SS'));
End;
/

Tan sencillo como sumar y restar.

4 thoughts on Manipulando fechas con Horas en PL/SQL y SQL

  1. Sin más detalles, la resta de variables “date” da fracciones de día (un número). Dicho de otro modo, si lo multiplicas la diferencia por 1440 (24hx60minutos) obtendrás los minutos entre una y otra.


    declare
    dt_ini date := TO_DATE('19/9/2014 07:00', 'DD/MM/YYYY HH24:MI');
    dt_fin date := TO_DATE('19/9/2014 17:20', 'DD/MM/YYYY HH24:MI');
    begin
    dbms_output.put_line (dt_ini);
    dbms_output.put_line (dt_fin);
    dbms_output.put_line ((dt_fin-dt_ini)*1140);
    end;
    /

    Si es un timestamp yo haria un cast( as date)


    declare
    dt_ini timestamp := TO_DATE('19/9/2014 07:00', 'DD/MM/YYYY HH24:MI');
    dt_fin timestamp := TO_DATE('19/9/2014 17:20', 'DD/MM/YYYY HH24:MI');
    begin
    dbms_output.put_line (dt_ini);
    dbms_output.put_line (dt_fin);
    dbms_output.put_line ((cast(dt_fin as date)- cast(dt_ini as date))*1140);
    end;
    /

  2. Hola amigo, buscando una solucion a mi problema me encontre esta web, talvez me puedas ayudar, tengo dos campos tipo datetime en el cual solo horas manejo con el formato hh:mi am corresponden a campos de horas de entrada y salida en los turnos de trabajo y necesito saber como poder compararlos para saber la cantidad de minutos entre uno y otro, podrias ayudarme, te lo agradeceria

  3. Lamentablemente, no entiendo muy bien a que te refieres.

    No obstante, si tu código es confuso y no ves muy bien como simplificarlos, lo mejor es encapsular la logica complicada en una función plsql, marcando claras las entradas y salidas. Al menos lo tendrás aislado y será más sencillo reescribirlo cuando tengas la idea feliz.

    Suerte.

  4. Es muy interesante una consulta puedo generar subtabals dentro de mis tablas par que pueda jalar las subtablas en un combo dandole un codigo menos tedioso el que estoy haciendo.
    Gracias por su atencion y reponder a mi pregunta.
    Atentamente

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *