旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

MongoDBでのDateの最大値

2014年10月26日

MongoDB で Date は最大いくつまで記録できるのかを調べました。

検証で使った MongoDB のバージョンは 2.6.4 です。

ECMAScript 上の仕様

大元の Date の仕様は、JavaScript の元である ECMAScript の ECMA 262 という規格によって定義されています。

以下、ECMA 262 内の該当部分の引用です。

15.9.1.1 Time Values and Time Range

A Date object contains a Number indicating a particular instant in time to within a millisecond. Such a Number is called a time value. A time value may also be NaN, indicating that the Date object does not represent a specific instant of time.

Time is measured in ECMAScript in milliseconds since 01 January, 1970 UTC. In time values leap seconds are ignored. It is assumed that there are exactly 86,400,000 milliseconds per day. ECMAScript Number values can represent all integers from −9,007,199,254,740,991 to 9,007,199,254,740,991; this range suffices to measure times to millisecond precision for any instant that is within approximately 285,616 years, either forward or backward, from 01 January, 1970 UTC.

The actual range of times supported by ECMAScript Date objects is slightly smaller: exactly −100,000,000 days to 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC. This gives a range of 8,640,000,000,000,000 milliseconds to either side of 01 January, 1970 UTC.

The exact moment of midnight at the beginning of 01 January, 1970 UTC is represented by the value +0.

ちなみに、最新の仕様書は、こちらからダウンロードできるようですが、この記事を書いている 2014/10/26 現在はリンクが落ちてて出来ませんでした。

なので、上記の引用は MDN の ECMA-262 Edition 5 から引用いたしました。
最新版は Edition 5.1 であるため少し古いのですが、まぁ大丈夫だろってことで。

で、いくつなの?

以下の更に抜粋した箇所によると、「UTCの開始時間から前後に 8,640,000,000,000,000 ミリ秒」とのことです:

This gives a range of 8,640,000,000,000,000 milliseconds to either side of 01 January, 1970 UTC.

MongoDB 上の仕様

まず、MongoDB のソースコードを見ると、コメントで「ECMA 262」と書いてあるところが多いので、雑に ECMA 262 準拠なのかと予測しました。

検証してみましょう:

> db.foo.save({x:new Date(8640000000000000)})
WriteResult({ "nInserted" : 1 })
> db.foo.save({x:new Date(8640000000000001)})
WriteResult({ "nInserted" : 1 })
> db.foo.save({x:new Date(-8640000000000000)})
WriteResult({ "nInserted" : 1 })
> db.foo.save({x:new Date(-8640000000000001)})
WriteResult({ "nInserted" : 1 })
> db.foo.find()
{ "_id" : ObjectId("544c848dad8d38018399bc95"), "x" : ISODate("275760-09-13T00:00:00Z") }
{ "_id" : ObjectId("544c848fad8d38018399bc96"), "x" : ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ") }
{ "_id" : ObjectId("544c8494ad8d38018399bc97"), "x" : ISODate("-271821-04-20T00:00:00Z") }
{ "_id" : ObjectId("544c8497ad8d38018399bc98"), "x" : ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ") }

仕様通りでした。