Tengo una pregunta para ustedes que va de fechas, memorias y lo que aquellas ocupan en éstas. No se si tiene una respuesta simple y lo que ocurre es que estoy especialmente obtuso o es que realmente no tan fácil como parece.
El formato
Timestamp de Fecha y Hora es el usado en SQL. Es un string ASCII que presenta el formato "
aaaa-mm-dd hh:mm:ss". Es muy fácil de leer (entender sólo viéndolo) pero muy ineficaz si tenemos que guardarlo en una memoria EEPROM de PIC por ejemplo. Ocupa 19 bytes (ó 20 si incluimos el \0)
El formato
Datetime es un entero de 32 bits y es el usado en muchos lenguajes de alto nivel. Consiste en un simple cómputo del
número de segundos que han transcurrido desde cierta echa que se utiliza de referencia. Es muy difícil de leer (entender sólo viéndolo) pero es muy eficaz si tenemos que guardarlo en una memoria EEPROM de PIC por ejemplo. Ocupa sólo 4 bytes.
Cuando nuestro PIC, ayudado por su inestimable amigo el DS1307, debe mostrar o transmitir una Fecha y Hora lo lógico es que lo haga en formato TimeStamp. Cuando lo tiene que almacenar en una EEPROM lo lógico es que lo haga en formato DateTime.
Esto nos lleva a tener que definir una serie de funciones que sean capaces de traducir a ambos formatos la expresión de una misma Fecha y Hora dada por sus respectivos componentes de
año, mes, día, hora,minuto y segundo.
Generar un Timestamp dados su componentes es trivial, se trata solo de formatear estas variables con un simple:
sprintf("%4Lu-%2u-%2u %2u:%2u:%2u",año,mes,día,hora,minuto,segundo);
Generar los componentes desde Timestamp es menos trivial, pero casi, dado que solo se trata de recoger los caracters dades su posición y hacerles la correspondiente conversión atoi().
Para generar un DateTime sobre un int32 solo tenemos que inicializar la variable e ir acumulando (sumando) segundos sobre ella según la tabla (simplificado olvidándonos por el momento de los años bisiestos):
1 Año 31536000
1 Mes_31 2678400 (Meses 1,3,5,7,8,10 y12)
1 Mes_30 2592000 (Meses 4,6,9 y 11)
1 Mes_28 2419200 (Mes 2)
1 Día 86400
1 Hora 3600
1 Minuto 60
1 Segundo 1
Cualquier fecha es fácilmente calculable con solo multiplicar y sumar.
Pero en lo que me atasco es en la función simétrica a ésta última. Dada una fecha en formato
int32 DateTime obtener sus componentes de
año, mes, día, hora,minuto y segundo El año es fácil ya que sería la parte entera de dividir DateTime por 31536000. Pero a partir de ahí no se por donde tirar. Si a continuación le resto el año obtenido multiplicado también por 31536000 tendría el DateTime sin el año y podría seguir extrayendo componentes.
Si hubiese codificado una fecha de por ejemplo el mes de marzo habría sumado en el Datetime las cantidades de 2678400 (correspondiente a Enero) y 2419200 (correspondiente a Febrero), las de marzo no las hubiese sumado como mes completo sino solo los correspondientes a los días transcurridos de él.
¿Como puedo extraer el dato de que el mes de Enero y el de Febrero han sido añadidos y que por lo tanto estamos en Marco? ¿alguna brillante idea? ¿algún insigne matemático puede decirme: Diego, eres tonto y simple ...?
Gracias amigos.