みずりゅの自由帳

主に参加したイベントやソフトウェア技術/開発について記録しています

Moment.jsのaddメソッドの実行では元の値も変わる

Moment.jsを利用して、現在日時を基準にして連続した日時データを取得しようとした際に確認した事象です。

const m = moment()
for (let i = 0; i < 30; i++) {
  let cur_date1 = m.add(i ,"minutes").format('YYYY-MM-DD HH:mm')
  //以下略
}

上のコードの期待としては「1分ずつ値が増えていく」でした。

しかし、実際には1回目こそ想定の値であるが、2回目は1分、3回目は3分、4回目は6分、5回目は10分、6回目は15分…と回を重ねるごとに、想定値とかけ離れていく。

理由としては、momentはミュータブルであり、addやsubtractのManipulate系メソッドの実行では元の値も変更されるため。


当然ながら、ドキュメントには書いてありました。

momentjs.com

Note: It should be noted that moments are mutable. Calling any of the manipulation methods will change the original moment.

If you want to create a copy and manipulate it, you should use moment#clone before manipulating the moment.

訳:momentsはミュータブルな点に注意すべきです。操作メソッドが呼び出されると元のmoment(の値)は変わります。もし、コピーを作成して操作をしたければ、操作前のmomentで「 moment#clone 」を使うべきです。


この記述に習い、基準となる日時のコピーを都度作成してそのコピーに対して追加を行う方式へ変更。

const m = moment()
for (let i = 0; i < 30; i++) {
  let cur_date1 = m.clone().add(i ,"minutes").format('YYYY-MM-DD HH:mm')
  //以下略
}

希望通り、1分ずつ加算される結果となりました。


実際に動作確認ページも作ってみました。
「add」を押すたびに、moment#clone していないもの(上)としているもの(下)の値の動きに違いが出てくるのがわかります。

https://rykawamu.github.io/js_code_sample/public/moment_add_sample.html