Convertir una fecha y hora en un número entero largo (y a la inversa)

Fecha y entero

Aquí describo un método sencillo para codificar una fecha y hora en un número entero. He procurado que el número generado sea lo más pequeño posible. Se trata de encadenar una serie de cálculos con el cociente y el resto de la división.
Proporciono el código fuente en Visual Basic.

Características

  • Para que el año ocupe menos espacio sólo utilizo los 2 últimos dígitos;
    es decir, cuento los años transcurridos desde el año 2000.
  • Todos los números deben empezar por cero.
    Por lo tanto le resto uno al mes y le resto uno al día.
  • No tengo en cuenta ni los años bisiestos ni los segundos bisiestos
  • Supongo que todos los meses sin excepción duran 31 días
  • La primera fecha es: 2000-01-01 00:00:00
  • La última fecha es:
    • Si es un entero con signo: 231-1 : 2066-10-25 03:14:07
    • Si es un entero sin signo: 232-1 : 2133-08-18 06:28:15

Tiempo Unix

El algoritmo utilizado recuerda a la forma de calcular el tiempo Unix. Las diferencias son:

  • El tiempo Unix tiene en cuenta los días que dura cada mes (incluyendo años bisiestos)
  • El tiempo Unix empieza a contar a partir del año 1970

Algoritmo

Fórmula para codificar la fecha y hora en un número entero

resultado = segundo + 60 *(minuto + 60 *(hora + 24 *(dia-1 + 31 *(mes-1 + 12 *(RESIDUO(año;100)))))

Para decodificar el número en fecha y hora hay que realizar una serie de divisiones enteras encadenadas:

número 60        
segundo cociente1 60      
  minuto cociente2 24    
    hora cociente3 31  
      día-1 cociente4 12
        mes-1 año-2000

Código Visual Basic para Aplicaciones 2012-12-05

Codifica la fecha y hora en un número entero

Public Function FechaHoraEnEnteroLargo(ByVal fecha As Date) As Long
Dim numero As Long
numero = Year(fecha) Mod 100
numero = numero * 12 + Month(fecha) - 1
numero = numero * 31 + Day(fecha) - 1
numero = numero * 24 + Hour(fecha)
numero = numero * 60 + Minute(fecha)
numero = numero * 60 + Second(fecha)
FechaHoraEnEnteroLargo = numero
End Function

Decodifica el número entero en fecha y hora

Public Function EnteroLargoEnFechaHora(ByVal entero As Long) As Date
Dim seg As Integer: seg = entero Mod 60: entero = entero \ 60
Dim min As Integer: min = entero Mod 60: entero = entero \ 60
Dim hor As Integer: hor = entero Mod 24: entero = entero \ 24
Dim dia As Integer: dia = entero Mod 31 + 1: entero = entero \ 31
Dim mes As Integer: mes = entero Mod 12 + 1: entero = entero \ 12
Dim año As Integer: año = entero + 2000
EnteroLargoEnFechaHora = DateSerial(año, mes, dia) + TimeSerial(hor, min, seg)
End Function

Comprobación del código

Public Sub ComprobarTodo()
ComprobarUno (DateSerial(2000, 1, 1))
ComprobarUno (DateSerial(2012, 12, 5) + TimeSerial(15, 55, 21))
ComprobarUno (DateSerial(2017, 5, 31) + TimeSerial(23, 59, 59))
ComprobarUno (Now)
ComprobarUno (EnteroLargoEnFechaHora(2 ^ 31 - 1))
End Sub

Private Sub ComprobarUno(fecha1 As Date)
Dim numero As Long
Dim fecha2 As Date

numero = FechaHoraEnEnteroLargo(fecha1)
fecha2 = EnteroLargoEnFechaHora(numero)

Debug.Print fecha1, numero, fecha2, fecha1 = fecha2
End Sub

Resultado esperado:

01/01/2000     0            01/01/2000    Verdadero
05/12/2012 15:55:21          415554921    05/12/2012 15:55:21         Verdadero
31/05/2017 23:59:59          559785599    31/05/2017 23:59:59         Verdadero
06/12/2017 19:45:46          576359146    06/12/2017 19:45:46         Verdadero
25/10/2066 3:14:07           2147483647   25/10/2066 3:14:07          Verdadero

Código Java 2017-12-07

Las características del código Java son un poco distintas al del VBA:

  • El long de Java (8 bytes) tiene mucha más capacidad que el long de VBA (4 bytes)
  • El rango de fechas es entre 0000-01-01 00:00:00 y 9999-12-31 23:59:59

Codifica la fecha y hora en un número entero

public static long codificar(short[] partes) {
long numero = 0;
numero = partes[YEAR];
numero = partes[MONTH] - 1 + numero * 12;
numero = partes[DAY] - 1 + numero * 31;
numero = partes[HOUR] + numero * 24;
numero = partes[MINUTE] + numero * 60;
numero = partes[SECOND] + numero * 60;
return numero;
}

Decodifica el número entero en fecha y hora

  public static short[] decodificar(long numero) {
short[] partes = new short[6];
partes[SECOND] = (short)(numero % 60); numero /= 60;
partes[MINUTE] = (short)(numero % 60); numero /= 60;
partes[HOUR] = (short)(numero % 24); numero /= 24;
partes[DAY] = (short)(numero % 31 + 1); numero /= 31;
partes[MONTH] = (short)(numero % 12 + 1); numero /= 12;
partes[YEAR] = (short)(numero);
return partes;
}

Descargas

Icono

Fecha y entero

El icono3d.svg lo he creado con InkScape

Comentarios

  1. 1 daniel chuquipoma 2017-12-06 Hace un año
    no funciona para los dias 31
  2. 2 daniel chuquipoma 2017-12-06 Hace un año
    amigo logre que funcione para los dias 31, yo utilizo java, igual me sirvio tu codigo. te envio lo que realize:
    public static String num_fecha(int num) {
    double va1= (double) num / 30;
    int dia = (num 0)+1;
    num = (int) num / 30;
    int mes = (int) num +1;
    double dife = mes+1 - (va1 +1);
    if (dife
  3. 3 Francisco 2017-12-06 Hace un año
    Tienes toda la razón. No funcionaba con el día 31.
    Ya lo he corregido para que vaya bien. Sólo he tenido que cambiar las apariciones del número 30 por el número 31.
    Muchas gracias por el aviso.
Proinf.net, ©2003-2018 ci 3.1.9 (CC) Esta obra está bajo una licencia de Creative Commons Este software está sujeto a la CC-GNU GPL