domingo, 26 de julio de 2009

Convertir segundos en años, meses, días, horas, minutos y segundos

Hace unos años un desarrollador me preguntó como podia hacer para convertir una columna de segundos acumulados en horas, minutos y segundos ya que se necesitaba mostrar esa información en un reporte para una compania de celulares. La pregunta me resultó muy interesante y la pude resolver de una forma bastante sencilla, utilizando solo sentencias sql (había encontrado otras soluciones pero utilizaban código VB o PL/SQL).
Un tiempo compartí la solución un sitio de Oracle y una semanas despues la publicaron en una sección de códigos utiles: "Convert Seconds to Hours, Minutes, and Seconds"
Viendo de armar una nota sobre seguridad de passwords en Oracle, necesitaba ver las cantidad de tiempo que demandaría crackear una password que requeria mostrar el tiempo necesario en romper una password medido en años, meses, dias, horas, minutos y segundos. Extendiendo el código referenciado arriba armé la siguiente función:

rop@DESA10G> create or replace function f_get_duration (p_sec number) return varchar2
2  is
3   l_dur varchar2(50);
4  begin
5   l_dur := to_char(extract(year from numtoyminterval(months_between(sysdate+(p_sec/60/60/24),sysdate),'month')),'0009') || ' ' ||
6            to_char(extract(month from numtoyminterval(months_between(sysdate+(p_sec/60/60/24),sysdate),'month')),'09')|| ' ' ||
7            to_char(extract(day from numtodsinterval ((sysdate+(p_sec/60/60/24))-add_months(sysdate,trunc(months_between(sysdate+
    (p_sec/60/60/24),sysdate))),'day' )),'009')|| ' ' ||
8            to_char(trunc(mod(p_sec,86400)/60/60),'09') || ' ' ||
9            to_char(trunc(mod(p_sec,3600)/60),'09') || ' ' ||
10           to_char(mod(mod(p_sec,3600),60),'09');
11   return l_dur;
12  end;
13  /

Función creada.
rop@DESA10G>

Abajo les paso unos ejemplos de uso:

Probemos con la cantidad de segundos en 22 horas:
rop@DESA10G> select f_get_duration(60*60*22) "YY MM DD HH MI SS" from dual;

YY MM DD HH MI SS
----------------------------------------------------------------------------------------------------
0000  00  000  22  00  00

Ahora con los segundos en 1 año y 22 horas:
rop@DESA10G> select f_get_duration((60*60*24*365)+(60*60*22))"YY MM DD HH MI SS" from dual;

YY MM DD HH MI SS
----------------------------------------------------------------------------------------------------
0001  00  000  22  00  00

Por ultimo con los segundos en 5 años y alrededor de 5 meses (puede variar porque tomo meses de 30 dias y dependerá del momento en que se corra)
rop@DESA10G>  select f_get_duration((60*60*24*365*5)+(60*60*24*30*5)) "YY MM DD HH MI SS" from dual;

YY MM DD HH MI SS
----------------------------------------------------------------------------------------------------
0005  04  026  00  00  00

rop@DESA10G>

Vemos que dió 5 años, 4 meses y 26 dias.

En una futura nota sobre algoritmos de fuerza bruta para "crackear" passwords les voy a mostrar usando la función extendida F_GET_DURATION cuanto tiempo se demoraría en romper una password de n caracteres.

2 comentarios:

  1. Gracias por el dato me sirvió de mucho!

    ResponderEliminar
    Respuestas
    1. Gracias por la función .... pero tuve que hacerle una pequeña correción ... Antes de los months_between le puse un round.. a cero porque cdo por ejemplo le pasas 86400 seg , es decir un dia daba que tambien era un mes...

      Eliminar