

moment().isValid()で日時の妥当性検証を実施しているのですが、24時00分00秒の日時妥当性検証が想定通り動作しません。

[code]

    // HH（=00～23）を想定している厳密比較なのでtrueは想定外
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD HH:mm:ss',true).isValid()); //true
    
[/code]

私としては、上記コードの判定結果は`false`となってほしいのですが、実際の挙動は`true`になってしまします。  
上記現象は、どのように実装すれば想定通りの結果を得ることができますでしょうか？

関連しそうな箇所のテストも実施しましたが`60分`、`60秒`等の挙動は想定通りでした。

[code]

    // ----------------------------
    //  24時00分00秒の振る舞い
    // ----------------------------
    
    // 厳密比較ではないので想定外とは言えない
    console.log(moment('2020-07-02 24:00:00').isValid());                            //true
    
    // 厳密比較ではないので想定外とは言えない
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD HH:mm:ss').isValid());      //true
    
    // HH（=00～23）を想定している厳密比較なのでtrueは想定外
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD HH:mm:ss',true).isValid()); //true
    
    // hh（=01～12）を想定している厳密比較なのでfalseは想定内
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD hh:mm:ss',true).isValid()); //false
    
    // kk（=01～24）を想定している厳密比較なのでtrueは想定内
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD kk:mm:ss',true).isValid()); //true
    
    // ----------------------------
    //  その他のfalseの確認
    // ----------------------------
    console.log(moment('2020-07-02 24:00:01','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 24:01:00','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 23:58:60','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 23:59:60','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 22:60:00','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 23:60:00','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
    console.log(moment('2020-07-02 23:60:60','YYYY-MM-DD HH:mm:ss',true).isValid()); //false
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
[/code]

`moment`の`2.27.0`を利用しています。


CC BY-SA 4.0
2020-07-08T15:21:51.887
68413
2020-07-13T19:49:42.110
2020-07-08T18:52:55.117
3068
41001
question
javascript
moment().isValid()での24時00分00秒の挙動について


[公式ドキュメント](https://momentjs.com/docs/#/parsing/string/)に載っている仕様なので、妥当性が`true`かつ翌日の判定になってしまうのは致し方ないものと思います。  
想定通りの挙動にする方法をWeb検索しても見つからず、文字列を`/`や` `で分割して自前で判定する提案がヒットする程度でした。(リンク先を失念)

公式ドキュメントから抜粋します。

> 2013-02-08 24:00:00.000 # hour 24, minute, second, millisecond equal 0 means
> next day at midnight

実際に`24:00:00`は翌日の判定となり、`24:00:01`は不正フォーマット判定になるのは不思議な仕様と感じます。  
しかしこの仕様になっている理由は確認できませんでした。

[code]

    // true
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD HH:mm:ss',true).isValid());
    
    // 2020-07-03 00:00:00 (翌日の0時判定)
    console.log(moment('2020-07-02 24:00:00','YYYY-MM-DD HH:mm:ss',true).format('YYYY-MM-DD HH:mm:ss'));
    
    // false (1秒増えるだけで不正フォーマット)
    console.log(moment('2020-07-02 24:00:01','YYYY-MM-DD HH:mm:ss',true).isValid());
    
[/code]


CC BY-SA 4.0
2020-07-13T01:17:19.980
68533
2020-07-13T01:17:19.980
9820
68413
answer


  * [Is there any workaround for handle datetime format as "24:00" #1174](https://github.com/moment/moment/issues/1174#issuecomment-25950746) \- moment/moment

によると、ISO 8601によって `24:00(:00)` は midnight
の表現として妥当である、と定められているため質問文にあるような挙動になっているようです。

当時の変更差分は[こちら](https://github.com/moment/moment/pull/1965/files)のようですが、少なくともこの時点では何らかの設定によって挙動を変える、というようなことは不可能そうです。  
(追記:
[現在の最新版コード](https://github.com/ichernev/moment/blob/d40760af83da2684cbfed136cafa7c943d397f92/moment.js#L1891)でも同様のように見えます)

* * *

補足:

ただし、上記のissueは2013年のものですが、現在の[該当Wikpediaの記述](https://en.wikipedia.org/wiki/ISO_8601#Times)では次のように更新されており、最新(2019年改訂？)の仕様では
`24:00` は許可されなくなっているようです。

> Midnight is a special case and may be referred to as either "00:00" or
> "24:00", except in ISO 8601-1:2019 where "24:00" is no longer permitted.


CC BY-SA 4.0
2020-07-13T13:12:15.243
68559
2020-07-13T19:49:42.110
2020-07-13T19:49:42.110
2808
2808
68413
answer