4

Time::Anytime

Posted by Paco Zarabozo on abril 2, 2010 in Código, Diario IT, Perl |

Este es un proyecto personal en Perl, que deseo compartir con quien desee participar. Me agradaría mucho ver que algo como esto es tomado por manos hispanoparlantes y llevado de forma exitosa a CPAN como tal.

La idea es muy simple: extender el rango de fechas de las funciones nativas localtime y gmtime, así como el conocido módulo Time::Local.

Mi idea es lograr que las funciones en cuestión funcionen sin ninguna otra limitación que el tamaño de dígitos manejables por el propio Perl. Esto quiere decir que la idea es que sea posible pasar como argumentos a localtime y gmtime tiempos mayores a 2147483647  (fecha dentro del año 2038, máximo valor admitido por perl en sistemas de 32 bits), así como tiempos en números negativos que permitan utilizar fechas menores a 1970.

Actualmente, el módulo es funcional, pero tiene algunos raros bugs que no he tenido mucho tiempo de analizar totalmente a fondo. Básicamente, se equivoca en ciertos momentos de fecha, casi siempre con error por 1 día. Es el mínimo de los casos y sólo sucede con fechas más allá de lo normal (ejemplo: fechas en 1814 o en 3023, años fuera del rango normal). Esos errores ocasionales ocurren básicamente cuando es mal calculado el ISDST o se agrega antes de tiempo un día extra a un año bisiesto (por ejemplo, durante algún loop que agrega el día extra antes de pasar por febrero).

Actualmente funciona bien (excepto por los raros momentos de error mínimo de tiempo). Es capaz de dar fechas en millones de años adelante y atrás de 1970. Cuando una fecha baja del año 1 (año -1, no existe el año cero), scalar localtime deja el año positivo y agrega un BC  al final, refiriéndose a años antes de Cristo.

 

Explicando la idea

La idea realmente es muy simple y no debería costar tanto trabajo, sólo cálculos bien pensados.  Estas son las bases:

1) Sólo existen 14 años diferentes. Todos los años son iguales a uno de esos 14 años: 7 normales y 7 bisiestos, cada uno comenzando en un día distinto de la semana. Basándose en esto, el módulo comienza por definir 14 fechas distintas que representan el inicio de un año entendible por CORE::localtime y posteriormente copia sus características modificando únicamente el año solicitado.

2) Para poder decidir qué tipo de año es un año en cuestión, hace falta saber qué año es basado únicamente en segundos, sean positivos o negativos.

3) Para poder decidir qué tipo de año es (una vez encontrado el año), es necesario saber en qué día de la semana comienza ese año.

4) Deben tenerse en cuenta en todos los cálculos, los años que tienen 366 días (bisiestos) y el momento en el que se está procesando una fecha (antes o después del posible febrero 29).

5) Una vez determinado el año de acuerdo a los segundos, y el día de la semana en que comienza el año, basta con tomar la fecha predefinida que tiene un año del mismo tipo (ya está definido en las variables del módulo) y pasarlo ya sea por CORE::localtime o CORE::gmtime para posteriormente cambiar el año por el que se pidió en la función original.

6) Están implementadas dentro del mismo módulo las funciones timelocal y timegm del módulo Time::Local. Procesan los datos de forma similar, calculando el tiempo sobre el tipo de año similar predefinido y posteriormente agregando o restando al valor de tiempo que se devolverá, el tiempo correspondiente al año que realmente se solicitó.

Instalación

Puedes descargar el módulo aquí:  Time::Anytime

Cualquier comentario, será bien recibido. Si deseas sólo probar el módulo, basta con que lo copies en la carpeta de módulos de tu instalación de Perl (ejemplo: /usr/site/lib/Time/Anytime.pm).

No está documentado aún. Pero una vez instalado, basta con poner lo siguiente en cualquier script:

#!/usr/bin/perl
use Time::Anytime;print scalar localtime(time) . “\n”;

my @localtime = localtime(60 * 60 * 24 * 365 * 3000); # Obtiene el año 3000

# Desde aquí podrás hacer uso normal de localtime, gmtime, timelocal y timegm:

print localtime; 

# Para obtener localtime de sistema sin pasar por este módulo (tal vez para comparar la salida):

@localtime = CORE::localtime(time);

 

Altamente bienvenidos los testers. Sólo pido por favor me informen de cualquier bug encontrado.

Altamente bienvenidos los colaboradores. Hace falta cualquier programador de Perl con buena experiencia y buenas prácticas de código.

Sé que será difícil encontrar respuestas a este proyecto; pero no imposible. Yo continuaré trabajando en el módulo para desaparecer en lo posible los márgenes de error que pueda tener.

Saludos. 🙂

Etiquetas: , , , , , , , , , , , , ,

4 Comments

  • Las nuevas versiones de Perl ya son compatibles con el año 2038. Te paso un enlace con el perldelta5120:

    http://search.cpan.org/~jesse/perl-5.12.0-RC3/pod/perl5120delta.pod#Y2038_compliance

  • Paco Zarabozo dice:

    ¡Hola Joaquín!

    Si bien será compatible con el año 2038 (aunque siga teniendo limitación hacia el futuro), sigue siendo incompatible con fechas inferiores a 1970.

    Con mi propuesta, perl deja de tener limitaciones en cuanto a fechas. El módulo actualmente puede representar millones de años al futuro o al pasado de forma precisa y rápida, excepto por las mencionadas fallas repentinas que requieren análisis de cálculo.

    Actualmente, si una persona se registra en tu sitio y le pides su fecha de nacimiento, tienes que recurrir a otro método para representar esa fecha, que bien puede ser separando día/mes/año en campos distintos o creando campos adecuados de fecha en tu base de datos, pero no puedes utilizar el valor de time() para ello. Al menos no sin este módulo.

    Javascript es capaz de representar cualquier fecha en el futuro o en el pasado, y puede devolverla en el formato que usa perl (con milisegundos) con (new Date).getTime() o (new Date).setTime(). Francamente, es vergonzoso que Perl no pueda hacerlo.

    Saludos.

  • Roberto dice:

    Cerebros como el tuyo le dan privilegios al mundo. Espero poder ver una versión estable pronto. 😀

  • Es bueno ver al talento en marcha. Intentaré participar con pruebas. Gracias.

Deja un comentario

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

Copyright © 2009-2017 Paco Zarabozo All rights reserved.
This site is using the Desk Mess Mirrored theme, v2.5, from BuyNowShop.com.