Moment.js: una mejor biblioteca de citas para JavaScript

Como sabe cualquier programador experimentado, las fechas y horas son increíblemente comunes en la mayoría de los códigos de nivel de aplicación. Puede usar fechas para rastrear la creación de un o...

Como sabe cualquier programador experimentado, las fechas y horas son increíblemente comunes en la mayoría de los códigos de nivel de aplicación. Puede usar fechas para realizar un seguimiento de la creación de un objeto, para realizar un seguimiento del tiempo transcurrido desde que ocurrió un evento o para guardar la fecha de un próximo evento. Sin embargo, no es fácil trabajar con las fechas, por lo que es importante tener una biblioteca que sea precisa y tenga una interfaz simple. El objeto Date de JavaScript estándar no es tan malo, pero carece de algunas características importantes y no siempre es fácil trabajar con él.

En este artículo, verá cómo Moment facilita el análisis, el formato y la manipulación de fechas y horas.

Análisis de fechas

Cuerdas

De forma predeterminada, Moment intenta analizar las cadenas de fecha utilizando el formato ISO 8601, que tiene una amplia gama de fechas válidas. Puede especificar tanta precisión de tiempo como desee en su fecha y hora utilizando este formato. Esto es excelente para nosotros, ya que las fechas pueden adoptar muchas formas diferentes, según el nivel de detalle que desee especificar.

Considere intentar analizar todos estos formatos diferentes por su cuenta:

  • 20160628
  • 2016-06-28T09
  • 20160628T080910,123
  • 2016-06-28 09:30:26.123
  • 2016-06-28 09:30:26.123+07:00

Como puede ver, no solo cambia la precisión del tiempo, sino que el formato en el que se especifica puede variar ampliamente, por lo que es tan importante tener un analizador de tiempo capaz.

En primer lugar, la forma más sencilla de crear un objeto momento es llamar al constructor sin argumentos:

1
2
> const moment = require('moment');
> let m = moment();

Esto creará una instancia de un objeto de fecha con la hora actual.

Para analizar una cadena de fecha y hora con Moment, simplemente pásela al constructor:

1
> let date = moment('2016-06-28 09:30:26.123');

Si por alguna razón, Moment no puede analizar la cadena que le diste, entonces volverá a utilizar el objeto integrado nueva Fecha() para el análisis.

Para verificar si su fecha fue analizada y válida, use el método .isValid():

1
2
3
4
> moment('2016-06-28 09:30:26.123').isValid();
true
> moment('derp').isValid();
false

Para todos los objetos de fecha creados con Moment, sin importar cómo los analice o los cree, la zona horaria del objeto será la zona horaria actual de forma predeterminada, a menos que se especifique directamente. Para recuperar la hora UTC, usa moment.utc() en su lugar. Para obtener más información sobre las zonas horarias, consulta la sección Zonas horarias de momento.

Especificación de formatos {#especificación de formatos}

Una de mis funciones de análisis favoritas en Moment es el analizador de cadena/formato. Es básicamente como un formateador de cadenas inversas. Usted proporciona la cadena de fecha y hora que se analizará y otra cadena que especifica el formato en el que se encuentra. De esta manera, puede usar cadenas de cualquier formato que desee y seguir usándolas cómodamente con Moment.

Por ejemplo, en los EE. UU. (por alguna razón) nos gusta formatear nuestras fechas como "Mes/Día/Año", mientras que en gran parte del resto del mundo las formateamos como "Día/Mes/Año". Esto deja mucho espacio para la confusión. Por ejemplo, ¿se supone que la fecha "06/11/2016" es el 6 de noviembre o el 11 de junio?

formatos de hora mundial
[Imagen: John Harding/Mona Chalabi via [El guardián](http://www.theguardian.com/news/datablog/2013/dec/16/why-do-americans-write-the-month-before-the- día)]{.pequeño}

Entonces, ¿cómo sabremos si sus fechas se están analizando correctamente? El uso de especificadores de formato como este garantiza que no haya ambigüedades en sus fechas, suponiendo que sepa de antemano en qué formato están. En el siguiente ejemplo, aún podemos analizar las fechas correctas a pesar de los formatos diferentes y potencialmente confusos. .

1
2
3
4
5
> let d1 = moment('11.06.2016', 'DD-MM-YYYY');
> let d2 = moment('06/11/2016', 'MM-DD-YYYY');

> d1.format();    // '2016-06-11T00:00:00-05:00'
> d2.format();    // '2016-06-11T00:00:00-05:00'

Tenga en cuenta que también usamos diferentes delimitadores en nuestras cadenas de fecha, "." y "/". Moment en realidad ignora todos los caracteres no alfanuméricos cuando usa estos formatos, por lo que no siempre debe preocuparse por hacer coincidir los formatos a la perfección.

Para obtener un conjunto completo de tokens de formato disponibles, consulte esta sección de los documentos de Moment.js.

Marcas de tiempo Unix

Como era de esperar, Moment también es capaz de analizar fechas enteras (tiempo unix), ya sea en formato de segundos o milisegundos:

1
2
> moment.unix(1467128085);      // Date in seconds from 1970
> moment(1467128085747);        // Date in milliseconds from 1970

La única diferencia en los tiempos resultantes es la precisión. millisecondDate tendrá un valor distinto de cero para el campo de milisegundos.

Fechas de impresión {#impresión de fechas}

En mi opinión, esta es una de las partes más útiles de Moment, principalmente porque el objeto Date incorporado de JavaScript no tiene un soporte muy bueno para él. Sorprendentemente, la única forma integrada de formatear con Date es usar el método Date.toLocaleDateString(), que parece bastante torpe y no tan flexible:

1
2
3
4
5
6
7
8
> let d = new Date(1467128085747);
> let options = {
...    weekday: 'long', year: 'numeric', month: 'short',
...    day: 'numeric', hour: '2-digit', minute: '2-digit'
... };

> date.toLocaleTimeString('en-us', options);
'Tuesday, Jun 28, 2016, 10:34 AM'

Con Moment, podemos lograr fácilmente este mismo formato con solo una línea de código (que mostraré en la siguiente sección).

Desglosaremos esto en algunas subsecciones. Primero, repasaremos el formato tradicional con tokens, luego mostraremos los formatos de fecha relativa disponibles (como "hace 18 minutos"), y finalmente mostraremos cómo formatear las fechas de manera diferente tipos de datos estructurados, como matrices, JSON o un “Objeto” simple de JavaScript.

Formateo

Usa el método .format() para mostrar la fecha como una cadena. Sin ningún argumento, imprime la cadena en la representación ISO 8601:

1
2
3
> let date = moment.unix(1467128085);
> date.format();
'2016-06-28T10:34:45-05:00'

De lo contrario, puede proporcionar su propio formato y personalizarlo a su gusto utilizando tokens.

1
2
> date.format('dddd, MMMM Do YYYY, h:mm a');
'Tuesday, June 28th 2016, 10:34 am'

Puede notar que esta es la misma representación que el ejemplo Date.toLocaleTimeString() de arriba, pero en una línea. Y todo lo que necesitó fue la cadena 'dddd, MMMM Do YYYY, h:mm a'.

Una vez más, la lista completa de tokens de formato se puede encontrar en el sitio web de documentación muy completo de Moment.

Formatos relativos {#formatos relativos}

A menudo, en las aplicaciones web, por ejemplo, es útil mostrar al usuario cuánto tiempo ha transcurrido desde que ocurrió un evento. En lugar de calcularlo usted mismo, Moment ofrece algunas funciones de utilidad para manejar este formato por usted.

En todos los casos, puede usar cualquier fecha del pasado o del futuro y la cadena devuelta reflejará el tiempo correcto.

Fuera de la caja, obtienes algunas opciones diferentes:

Tiempo a partir de ahora

Suponiendo que la fecha de hoy sea el 1 de julio de 2016, obtendrá el siguiente formato relativo:

1
2
3
4
> moment({year: 2016, month: 3, day: 13, hour: 10}).fromNow();
'3 months ago'
> moment({year: 2016, month: 9, day: 23, hour: 10}).fromNow();
'in 4 months'

Opcionalmente, puede pasar un ‘booleano’ a ‘.fromNow()’ diciéndole si debe o no incluir la cadena "ago" (o "in") en el formato. De esta manera, aún puede personalizar fácilmente la cadena relativa si es necesario.

1
2
> moment({year: 2016, month: 3, day: 13, hour: 10}).fromNow(true);
'3 months'

Tiempo desde la fecha

1
2
3
4
5
6
7
> let may = moment({year: 2016, month: 5, day: 3});
> let october = moment({year: 2016, month: 10, day: 9});
>
> may.from(october);
'5 months ago'
> october.from(may);
'in 5 months'

Hora de ahora

1
2
3
4
> moment({year: 2016, month: 3, day: 13, hour: 10}).toNow();
'in 3 months'
> moment({year: 2016, month: 9, day: 23, hour: 10}).toNow();
'4 months ago'

Tiempo hasta la fecha

1
2
3
4
5
6
7
> let may = moment({year: 2016, month: 5, day: 3});
> let october = moment({year: 2016, month: 10, day: 9});
> may.to(october)
'in 5 months'
> 
> october.to(may)
'5 months ago'

Es posible que haya notado que los métodos "from" y "to" se pueden intercambiar, dependiendo de las fechas que se pasan en el argumento. Todo es relativo.

Fechas y horas estructuradas

En algunos casos, puede ser más conveniente tener sus datos de fecha en un formato estructurado, posiblemente para usarlos en un algoritmo o serialización. Moment ofrece algunas formas diferentes de formatear los datos en estructuras de datos:

  • toDate(): Devuelve la fecha del Momento como una Fecha de JavaScript
  • toArray(): Devuelve datos de fecha como una matriz - [ 2016, 5, 28, 10, 34, 45, 747 ]
  • toJSON(): Devuelve la cadena de fecha ISO ajustada a UTC - "2016-06-28T15:34:45.747Z"
  • toISOString(): Devuelve la cadena de fecha ISO ajustada a UTC - "2016-06-28T15:34:45.747Z"
  • toObject(): Devuelve un ‘Objeto’ JavaScript simple con datos de fecha - ‘{años: 2016, meses: 5, fecha: 28, horas: 10, minutos: 34, segundos: 45, milisegundos: 747} `
  • toString(): Devuelve una cadena formateada similar a Date.toString() - "Tue Jun 28 2016 10:34:45 GMT-0500"

Manipulación de fechas {#manipulación de fechas}

La capacidad de manipular fechas también es muy importante para muchas aplicaciones. Y esto tampoco es tan simple como su aritmética normal: manipular fechas es difícil. ¿Puedes descifrar fácilmente estas adiciones/sustracciones de fecha/hora? No es una tarea fácil de programar.

  • 21 de febrero + 13 semanas
  • 3:14 am + 424 minutos
  • 1 de julio - 1899400140 milisegundos

Ahora, ¿y si es un año bisiesto? ¿O un año con un segundo intercalar? Por suerte para ti, no necesitas resolver esto por ti mismo. Momento ya tiene para ti.

Existen bastantes métodos de manipulación del tiempo, por lo que solo repasaremos los más utilizados:

Sumar/Restar

Use un número/cadena o un objeto para manipular la fecha:

1
2
> moment().add(7, 'days');
> moment().subtract({days:13, months:3});

El encadenamiento también funciona bien:

1
> moment().add({hours: 7}).subtract(13, 'minutes');

Inicio/Fin del tiempo

Estos métodos de conveniencia establecen la fecha/hora al final de la unidad de tiempo dada. Por ejemplo, si tiene una cita con una hora de 2:15, pero necesita que sea el comienzo del día, usaría:

1
> moment().startOf('day');

Esto establecerá la hora a las 12:00 am del mismo día. Lo mismo funciona para año, mes, hora y muchos más.

1
> moment().endOf('year');   // sets date to 12-31-2016 23:59:59.999

Descubrí que esto es muy útil en las aplicaciones de informes donde los usuarios pueden seleccionar marcos de tiempo para los informes, como Google Analytics. Para recuperar los datos correctos, debe tener el rango correcto.

Zonas horarias de momentos

Moment admite la configuración de desplazamientos de zona horaria listos para usar, pero si necesita un mejor soporte de zona horaria, entonces debería considerar usar moment-timezone.

Esta biblioteca le permite especificar zonas horarias por ciudad, región u otros identificadores, lo que puede simplificar mucho las cosas para las aplicaciones orientadas al usuario.

Para usarlo, instálelo con npm y require() en lugar de moment:

1
> const moment = require('moment-timezone');

Con más de 550 identificadores de zona horaria, puede dividir sus especificadores de zona horaria por varias categorías y nombres regionales:

  • Nombre de la zona horaria: EE. UU./Central, EE. UU./Este, EE. UU./Montaña, etc.
  • Ciudad: América/Chicago, América/Los Ángeles, Asia/Dubai, Australia/Sydney, etc.
  • Desplazamiento GMT: Etc./GMT+6, Etc./GMT-2, Etc./GMT0, etc.

Para obtener una lista completa de identificadores de zona horaria, puede ver una lista completa de nombres ejecutando:

1
2
> const moment = require('moment-timezone');
> moment.tz.names()

Para usar estos identificadores para configurar la hora y la zona horaria con el método .tz():

1
2
3
4
> moment.tz({year: 2016, month: 6, day: 30, hour: 11}, 'America/Los_Angeles').format();
'2016-07-30T11:00:00-07:00'
> moment.tz({year: 2016, month: 6, day: 30, hour: 11}, 'America/Chicago').format();
'2016-07-30T11:00:00-05:00'

Conclusión

Trabajar programáticamente con fechas y horas es difícil, pero no tiene por qué ser lo más difícil que haga. Moment es un gran ejemplo de una biblioteca que simplifica mucho un tema difícil con una API limpia y fácil de usar.

Además del análisis, el formato y la manipulación que proporciona Moment, también hay soporte adicional para zonas horarias a través del paquete moment-timezone. Haga la vida más fácil para usted y sus usuarios agregando un mejor soporte para las zonas horarias.

¿Qué otras características de Moment usas con frecuencia? ¡Cuéntanos en los comentarios!