¿Cómo soluciono la mutabilidad en moment.js?

106

Me he encontrado con un problema en el que tengo que almacenar los valores iniciales de un objeto de momento, pero tengo problemas para evitar que mi variable cambie junto con el objeto original.

Desafortunadamente, Object.freeze () no funciona, porque moment.js devuelve un error de "Fecha no válida" cuando intento formatear eso.

Shengbo1618
fuente
3
¿Y el código parece…? Si desea almacenar el valor inicial, almacene el valor de tiempo, disponible mediante el método valueOf o la conversión implícita a número.
RobG
una vez que su variable está configurada, está configurada, no cambiará automágicamente, así que busque no configurarla una y otra vez
john Smith

Respuestas:

184

Hay un complemento Moment.js en NPM llamado momento congelado : puede usar moment().freeze()en lugar de Object.freeze(moment()).

De lo contrario, vanilla Moment.js tiene un clonemétodo que debería ayudarlo a evitar problemas de mutabilidad, por lo que podría hacer algo como esto:

var a = moment(),
    b = a.clone(); // or moment(a)

ACTUALIZAR:

Han pasado dos años desde que escribí esta respuesta. En este momento, ha surgido otra biblioteca para trabajar con fechas y ha ganado mucha tracción: https://date-fns.org/

Esta biblioteca es inmutable de forma predeterminada y sigue una arquitectura modular y funcional, lo que significa que se adapta mejor a la agitación de árboles y la agrupación del lado del cliente. Si está trabajando en un proyecto que hace un uso extensivo de Webpack en el lado del cliente y descubre que Moment.js le está causando problemas con su compilación, o incluso si la mutabilidad de Moment.js le está causando muchos dolores de cabeza, entonces debería date-fnsintentarlo.

barba de afeitar
fuente
Bueno, estoy usando moment.js en el complemento fullCalendar y resulta que estaba obteniendo los datos del objeto moment de un estado posterior de mi evento de lo que se suponía. Sin embargo, los problemas de mutabilidad son definitivamente una cosa con moment.js, así que muchas gracias por la sugerencia y lamento haber perdido el tiempo.
Shengbo1618
24
Puede manipular la momentvariable almacenada sin mutarla: simplemente use clone () así:zz = moment(); zz.clone().add(3, 'h').toISOString();
Quake1TF
5
Tenga en cuenta que date-fns tiene un soporte de zona horaria muy deficiente y no admite fechas UTC.
mjuopperi
3
Lo he estado usando date-fnsdurante un tiempo, pero desde entonces tuve que saltar al código heredado usando Moment y, vaya, ¿esta publicación me salvó de saltar por una ventana?
Yuschick
dayjsTambién es una buena alternativa ya que tiene APIs similares a Moment.js con naturaleza inmutable. (A partir de marzo de 2019, carece de soporte de zona horaria, pero esta es una biblioteca bastante nueva y puedo observar que el trabajo está en curso).
Tomoyuki Aota
2

Es una vieja pregunta y disculpas por la autopromoción descarada, ya que esta no es mi intención, solo espero que ayude a alguien.

Además de lo que dice razorbeard ( .clone()etc.), creé un módulo NPM que adjunta métodos inmutables a lo que sea que Moment.js venga de fábrica. La intención no es romper el código existente, por lo que el módulo agrega nuevos métodos con un Immuapéndice a su nombre.

Cada instancia devuelta por la fábrica de momentos se decorará con métodos inmutables, por ejemplo moment().startOf(), tendrá el correspondiente startOfImmu(), add()tendrá , addImmu()etc. Cada uno de ellos devuelve un nuevo momento en lugar de modificar el existente. Para usarlo, simplemente pase de momentfábrica a momentImmutableMethodspara obtener acceso a nuevos métodos inmutables. Ejemplo:

var moment = require('moment'); // or moment-timezone 
import { momentImmutableMethods } from 'moment-immutable-methods';

// to decorate instances with immutable methods we need to extend moment factory as below:
momentImmutableMethods(moment);

// now every instance returned by moment will have Immu methods attached.


// IMMUTABLE EXAMPLE
// we using immutable methods that were attached to every instance, these have Immu appended to original name
const ddd = moment({
  hour: 5,
  minute: 10
});
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
const eee = ddd.startOfImmu('day');
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
console.log(ddd === eee);
// false
const fff = eee.startOfImmu('month');
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
console.log(ddd === fff);
// false
console.log(eee === fff);
// false
console.log(ddd.format('DD/MM/YY HH:mma'));
// "14/04/18 05:10am"
console.log(eee.format('DD/MM/YY HH:mma'));
// "14/04/18 00:00am"
console.log(fff.format('DD/MM/YY HH:mma'));
// "08/04/18 00:00am"

Está en NPM en https://www.npmjs.com/package/moment-immutable-methods

spirytus
fuente