"El buen diseño es obvio. El gran diseño es transparente"
- Joe Sparano

Aprende a usar moment.js

9 minutos de lectura
Fecha: 5/12/2018

Si hablamos de librerías relacionadas con front-end mi consejo es: aprende a usar moment.js, no quiero parecer dogmático pero es así, raro me parece no caer nunca en un proyecto donde tengamos que formatear fechas y trabajar con ellas, y llegados a ese punto usar moment.js te va a venir muy pero que muy bien.

Esta entrada no es un tutorial completo con todas las cosas que puedes hacer (que son muchas) con moment.js, para eso tienes la documentación en su página oficial que lo explica todo perfectamente, es para que tengas un punto de partida y para explicar algunas tareas que personalmente hago bastante con esta librería. Instalación

Instalar la librería es un muy fácil, puedes descargarla con npm, con bower, desde un cdn

// Con npm
npm install moment

// Con bower
bower install --save moment

// Con un cdn
https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js

O descargarte el proyecto de github y listo, aquí tienes la página.

Luego dependiendo de como sea tu proyecto hay que importarlo, como cualquier otra librería, os dejo algunas maneras.

// Con node
var moment = require('moment');

// Con typescript
import * as moment from 'moment';

// Directamente en la página
<script src="moment.js"></script>

Y ahora que tu proyecto ya lo tiene es hora de empezar a usar moment.js, pero antes veamos que podemos hacer para manipular fechas sin la librería… Fechas en Javascript

El propio lenguaje ya nos proporciona el objeto Date para manipular fechas, para hacer cosas no demasiado complejas funciona bien, pero obviamente no cubre todas las funcionalidades que tiene la librería moment.js.

Básicamente podemos pedirle que nos de la hora de actual usando el constructor sin parámetros, o asignar nosotros una fecha asignando parámetros al constructor, os pongo los ejemplos.

new Date() // Sin parámetros para la fecha actual… // Devuelve 2018-11-03T11:45:18.995Z

new Date(2018, 11, 24, 10, 33, 30, 0) // Los parámetros son (year, month, day, hours, minutes, seconds, milliseconds) // Devuelve 2018-12-24T09:33:30.000Z

new Date(86400000); // Aquí pasamos milisegundos, y devuelve la fecha del 1 de Enero de 1970 a las 12 de la 00:00 más esos ms // Devuelve 1970-01-02T00:00:00.000Z

new Date(“October 15, 2018 12:05:00”); // Por último podemos pasar un DateString // Devuelve 2018-10-15T10:05:00.000Z

Estas son básicamente las opciones que tenemos de forma nativa para crear una fecha, acordarse de todos esos parámetros si quieres especificar algo es la muerte y además tiene sus propias reglas como que el numérico que especifica los meses va de 0 a 11 (que conste que en moment.js también es así).

Luego esta el tema de los milisegundos, sin comentarios, para un timestamp esta bien pero dudo que nadie intente introducir una fecha calculando los milisegundos que han pasado desde el 1 de Enero de 1970 a las 00:00.

Tal vez el DateString sea la manera más cómoda de introducirlo pero nos faltan cosas.

Es cierto que una vez tenemos la fecha podemos extraer datos con un montón de métodos que tiene disponibles, pero solo para explicar alguna de las carencias es que si yo quiero solamente que me diga el nombre del mes en un idioma me tengo que crear un método, ya no hablemos de sumar y restar fechas… Que cosas podemos hacer al usar moment.js

Pues podemos hacer muchas cosas, pero como esto es un tutorial voy a explicar solo unas cuantas, las básicas y algunas que son interesantes y le dan ese valor añadido que hace de esta librería un imprescindible.

 

moment.js

 

Obtener la fecha actual

var now = moment();

Obtener la fecha actual y formatearla inmediatamente a lo que prefieras

moment().format(‘DD/MM/YYYY HH:mm’);

Antes de continuar, estas son las opciones para formatear la fecha de moment.js, aunque no es necesario memorizar todas si que esta bien conocer las más habituales, en cualquier caso si no te acuerdas de alguna puedes usar esto a modo de cheatsheet. 1 Presets horarios LT 8:30 PM LTS 8:30:25 PM 2 Presets de fecha LL August 2 1985 ll Aug 2 1985 3 Presets de fecha y hora LLL August 2 1985 08:30 PM lll Aug 2 1985 08:30 PM 4 Fecha, hora y día de la semana LLLL Thursday, August 2 1985 08:30 PM llll Thu, Aug 2 1985 08:30 PM Día de la semana d 0..6 dd Su ddd Sun dddd Sunday Año YY 13 YYYY 2013 Mes M 1..12 (Jan is 1) Mo 1st..31st MM 01..12 (Jan is 1) MMM Jan MMMM January Trimestre Q 1..4 Qo 1st..4th Dia D 1..31 Do 1st..31st DD 01..31 Dia del año DDD 1..365 DDDo 1st..365th DDDD 001..365 Semana del año w 1..53 wo 1st..53rd ww 01..53 Modo 24 horas H 0..23 HH 00..23 Modo 12 horas h 1..12 hh 01..12 Minutos m 0..59 mm 00..59 Segundos s 0..59 ss 00..59 AM/PM a am A AM Timezone offset Z +07:00 ZZ +0730 Décimas S 0..9 Centésimas SS 00..99 Milésimas SSS 000..999 Unix timestamp X Unix timestamp (milésimas) x

 

Acabamos de ver como es posible formatear la salida como nos de la gana, literalmente podemos formatearla a nuestro gusto, y sino pensad en que podría hacer algo como esto…

moment().format(‘DD||MM||YYYY (HH.mm)’); // Devuelve esto -> “14||11||2018 (19.21)

Obviamente formatear una fecha de esta manera es un poco extraño, pero el caso es que es posible, pero una vez empezamos a guardar fechas con esta estructura en nuestra aplicación es normal que lleguemos a un punto donde tengamos que operar con ellas.

Veamos en base al ejemplo anterior como podemos parsear la fecha de vuelta.

var mi_fecha = moment(‘14||11||2018 (19.21)’, ‘DD||MM||YYYY (HH.mm)’); // Devuelve un objeto Moment válido con la fecha parseada console.log(mi_fecha._d); // Devuelve un objeto Date -> 2018-11-14T18:21:00.000Z

Incluso podemos combinar ambos procesos, el de parseado de una fecha y su posterior formateado, esto ya es un poco mas enrevesado pero al menos a mí me ha sido útil.

Imaginemos ahora que tenemos una fecha que nos llega en formato MM-DD-YY y nosotros la queremos formateada en DD/MM/YYYY. Pues tan sencillo como hacer esto.

moment(‘11-14-18’, ‘MM-DD-YY’).format(‘DD/MM/YYYY’); // Devuelve esto -> “14/11/2018”

Como vemos manipular las fechas con moment.js es tremendamente sencillo.

Pasar la fecha con un string válido

var day = moment(“2018-12-25”);

Comprobar si el string es válido

var day = moment(“2018-12-25”); day.isValid();

Hasta ahora hemos visto cosas útiles orientadas al parseo y formateo, pero si hay algo que de verdad aporta valor a esta librería es la capacidad para operar con fechas, veamos cuales son. Sumar y restar a las fechas

Sin duda esta es una de las funcionalidades más útiles que tienes al usar moment.js, básicamente porque de manera nativa no tenemos métodos para hacer algo así y acabamos implementando funciones propias que son bastante difíciles de entender y no suelen ser nada flexibles.

La manera típica de hacer esto es calcular cuanto tiempo queremos sumar o restar en milisegundos y después hacer la cuenta usando el método getTime para pasar una fecha también a milisegundos, toda esta película te la ahorras con la librería moment.js que ya tiene funciones para ello.

Por ejemplo para sumar fechas hacemos así…

// Sumar 7 días a la fecha actual moment().add(7, ‘days’);

// Forma abreviada de escribirlo moment().add(7, ‘d’);

// Sumar 1 mes a la fecha actual moment().add(1, ‘months’);

// Sumar 3 mes a una fecha específica var mi_fecha = moment(‘11/14/18’, ‘MM/DD/YY’).add(3, ‘months’); console.log(mi_fecha._d); // Devuelve 2019-02-13T23:00:00.000Z

La verdad es que podemos hacer muchas cosas y de muchas formas distintas, el caso es que todo es muy sencillo, incluso podríamos concatenar sumas sin ningún problema.

Para las restas es exactamente lo mismo, solo que el método que usamos en vez de llamarse add se llama subtract, igualmente adapto los ejemplos de arriba para tener una referencia.

// Restar 7 días a la fecha actual moment().subtract(7, ‘days’);

// Forma abreviada de escribirlo moment().subtract(7, ‘d’);

// Restar 1 mes a la fecha actual moment().subtract(1, ‘months’);

// Restar 3 mes a una fecha específica var mi_fecha = moment(‘11/14/18’, ‘MM/DD/YY’).subtract(3, ‘months’); console.log(mi_fecha._d); // Devuelve 2018-08-13T22:00:00.000Z

Diferencia entre dos fechas

Es interesante también el que nos permita saber cual es la diferencia de tiempo entre dos fechas dadas.

Ademas permite formatear esa diferencia para que lo represente en distintas unidades de tiempo, por ejemplo, puedes pedir la diferencia en horas, días, meses, un timestamp de unix…

Estos son algunos ejemplo de lo que podemos hacer, vamos a partir de que tenemos estas dos fechas…

var fecha1 = moment(‘14/11/2018 19:15:00’, ‘DD/MM/YYYY HH:mm:ss’); var fecha2 = moment(‘17/11/2018 09:45:30’, ‘DD/MM/YYYY HH:mm:ss’);

Ahora vamos usar el método diff para extraer la diferencia.

fecha2.diff(fecha1); // Devuelve el timestamp -> 225000000

fecha2.diff(fecha1, ‘minutes’); // Devuelve la diferencia en minutos (truncado) -> 3750 fecha2.diff(fecha1, ‘minutes’, true); // Devuelve la diferencia en minutos con decimales -> 225000000

fecha2.diff(fecha1, ‘days’); // Devuelve la diferencia en días (truncado) -> 225000000 fecha2.diff(fecha1, ‘days’, true); // Devuelve la diferencia en días con decimales -> 225000000

Básicamente lo que estamos haciendo es restar a la fecha2 la fecha1 y la diferencia es el resultado, en este caso el resultado es positivo porque la fecha2 es mayor que la fecha1.

En el caso de que hubiéramos hecho al revés (restar la fecha2 a la fecha1) no habría problema, simplemente al restar una fecha mayor a una mas pequeña el resultado será negativo, igualmente es útil. Consultas a fechas

Otra de las peculiaridades al usar moment.js es la capacidad para hacer ciertas consultas a una fecha, es decir, para preguntar si cumplen una condición determinada.

Pensemos en que tienes una aplicación donde vas a ir recibiendo fechas (con los valores que sean) y quieres automatizar que se filtren si a partir de cierto día o entre un rango, usando las consultas que moment.js pone a nuestro alcance es muy sencillo. Veamos cuales son:

Comprobar si las fechas son iguales

moment(‘2018-08-11’).isSame(‘2018-08-11’); // Devuelve true

moment(‘2018-08-11’).isSame(‘2015-11-05’); // Devuelve false

Consultar si una fecha es posterior a otra, o si es igual o posterior

// Consulta si es posterior moment(‘2018-08-11’).isAfter(‘2018-08-10’); // Devuelve true moment(‘2018-08-11’).isAfter(‘2018-08-11’); // Devuelve false moment(‘2018-08-11’).isAfter(‘2018-08-12’); // Devuelve false

// Consulta si es igual o posterior moment(‘2018-08-11’).isSameOrAfter(‘2018-08-10’); // Devuelve true moment(‘2018-08-11’).isSameOrAfter(‘2018-08-11’); // Devuelve true moment(‘2018-08-11’).isSameOrAfter(‘2018-08-12’); // Devuelve false

Consultar si una fecha es anterior a otra, o si es igual o anterior

// Consulta si es anterior moment(‘2018-08-11’).isBefore(‘2018-08-10’); // Devuelve false moment(‘2018-08-11’).isBefore(‘2018-08-11’); // Devuelve false moment(‘2018-08-11’).isBefore(‘2018-08-12’); // Devuelve true

// Consulta si es igual o anterior moment(‘2018-08-11’).isSameOrBefore(‘2018-08-10’); // Devuelve false moment(‘2018-08-11’).isSameOrBefore(‘2018-08-11’); // Devuelve true moment(‘2018-08-11’).isSameOrBefore(‘2018-08-12’); // Devuelve true

Por último (aunque no son todas las consultas que podemos hacer) veamos como podemos consultar si la fecha esta dentro de un rango

moment(‘2018-08-11’).isBetween(‘2018-08-30’, ‘2018-08-01’); // Devuelve false moment(‘2018-08-11’).isBetween(‘2018-08-01’, ‘2018-08-30’); // Devuelve true moment(‘2018-08-11’).isBetween(‘2018-08-01’, ‘2018-08-11’); // Devuelve false moment(‘2018-08-11’).isBetween(‘2018-08-01’, ‘2018-08-12’); // Devuelve true

He puesto 4 casos de uso para explicar ciertas peculiaridades

El primer caso devuelve false porque la fecha de inicio es mayor que la de fin, de manera que no da igual el orden en el que metamos las fechas del rango. La segunda devuelve true, y es igual que el primer ejemplo pero metiendo correctamente las fechas del rango. El tercer ejemplo devuelve false, lo que indica que las fechas del rango no están incluidas en la consulta El ultimo es igual que el tercero, pero le añadimos un día mas al final del rango para que ya funcione.

 

No voy a continuar explicando las funcionalidades que tiene, pero hay muchas más, si las quieres consultar aquí tienes la documentación oficial, pero sin duda creo que queda claro que esta librería contiene muchísimas utilidades para trabajar con fechas, y que es muy interesante usar moment.js en nuestros desarrollos.