Archive for the 'JSDates' Category

JSDates, simples funciones de fecha en JavaScript/NodeJS (1)

Sunday, January 17th, 2016

En el proyecto MoneyPool y en otros, me ha tocado manipular fechas. En general, he seguido el camino más sencillo, y represento las fechas según los casos de uso que necesito. En ese proyecto, por ejemplo, necesita fechas de días, para ordenar movimientos o para recuperar movimientos en un rango de fechas. Antes que usar el objeto Date de JavaScript, decidí usar lo más simple: un simple string con formato YYYYMMDD (cuatro dígitos de año, dos de mes, y dos de días). Vean que no incluyo formateo ni por ejemplo, zona horaria, PORQUE los casos de uso que tengo no los necesitan. Y cuando los necesite, lo agregaré con confianza, porque he seguido el flujo de trabajo de TDD (Test-Driven Development).

Pero en esta semana, en un proyecto no público, aparecieron otros casos de uso, como agregar simplemente días, meses, y convertir a formatos de ISO String (este caso de uso lo podría discutir, pero así es como lo espera el programa cliente que va a consumir una API que exponemos). Podría usar algún módulo ya escrito, como moment, pero me pareció que para el uso que necesitamos ahora, no hacía falta. Ya saben como pienso: prefiero lo simple a lo fácil. Así que si hay que escribir código para casos de uso nuevos, no reniego y lo hago, aunque podría evitarlo con importar una librería. Pero insisto: mis decisiones se guían por simplicidad, baby steps, guiado por caso de uso, y todo eso me decía al oído “no hace falta moment… “ 😉

Así que ayer, siguiendo TDD, me puse a escribir:

https://github.com/ajlopez/JSDates

usando NodeJS, pero debería servir también desde el browser (podría escribir test adecuados). La idea es tener una representación simple de una fecha (no fecha/hora), un fecha/hora, y por ahora, poder sumarle días, meses, y convertir el resultado a un Date nativo de JavaScript cuando haga falta.

Un test típico:

exports['add months'] = function (test) {
    var date = jsdates.date(2016, 1, 12).addMonths(2);
    var ndate = new Date(2016, 2, 12);
    
    test.equal(date.year(), ndate.getFullYear());
    test.equal(date.month(), ndate.getMonth() + 1);
    test.equal(date.day(), ndate.getDate());
    
    test.equal(date.hours(), 0);
    test.equal(date.minutes(), 0);
    test.equal(date.seconds(), 0);
};

También hay funciones para conseguir el today (fecha actual) y el now (fecha/hora actual) y comenzar a manipularlos. Un test sobre now:

exports['create now'] = function (test) {
    var now = jsdates.now();
    
    test.ok(now);
    test.equal(typeof now, 'object');
    
    var date = new Date();
    
    test.equal(now.year(), date.getFullYear());
    test.equal(now.month(), date.getMonth() + 1);
    test.equal(now.day(), date.getDate());
    if (now.hours() === date.getHours())
        if (now.minutes() === date.getMinutes())
            test.ok(now.seconds() === date.getSeconds() || now.seconds() + 1 === date.getSeconds())
        else {
            test.ok(now.minutes() + 1 === date.getMinutes());
            test.equal(now.seconds(), 59);
            test.equal(date.getSeconds(), 0);
        }
    else {
        test.equal(now.hours() + 1, date.getHours());
        test.equal(now.minutes(), 59);
        test.equal(date.getMinutes(), 0)
    }
};

Vean que es algo frágil. Podría ser que el now que devuelve la librería no coincida en valores con el new Date() del tests. Lo que hice fue agregar un test experimental, usando el viejo truco de inyectarle a la librería cuál es el valor de now que quiero que use, en vez de usar new Date() nativo:

exports['use and create now'] = function (test) {
    var date = new Date();
    
    jsdates.set('now', date);
    
    var now = jsdates.now();
    
    test.ok(now);
    test.equal(typeof now, 'object');
    
    var date = new Date();
    
    test.equal(now.year(), date.getFullYear());
    test.equal(now.month(), date.getMonth() + 1);
    test.equal(now.day(), date.getDate());
    test.equal(now.hours(), date.getHours());
    test.equal(now.minutes(), date.getMinutes());
    test.equal(now.seconds(), date.getSeconds());
};

Todo es mejorable, y teniendo TDD, me aseguro que cualquier cambio no rompa la conducta esperada. La cuestión que luego de unas líneas de código, ya lo tengo publicado y usado en otro proyecto, habiendo podido saltearme el uso de moment. Seguramente habrá otras librerías simples, pero me gusta practicar programación y en especial TDD.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez