FirebaseのクラウドデータベースであるCloud Firestoreは、Timestamp形式での日付・時刻の保存に対応しており、その日付順にソートすることができます。
const db = firebase.firestore()
const data = await db.collection('messages')
.orderBy('date', 'asc')
.limit(limit)
.get()
.then(querySnapshot => {
return querySnapshot.docs.map(doc => doc.data())
})
また、startAt
やendBefore
といった特定の期間で区切ることもできます。
const db = firebase.firestore()
const startDate = new Date(`2019/01/01 00:00:00`)
const endDate = new Date(`2020/01/01 00:00:00`)
const data = await db.collection('messages')
.orderBy('date', 'asc')
.startAt(startDate)
.endBefore(endDate)
.limit(limit)
.get()
.then(querySnapshot => {
return querySnapshot.docs.map(doc => doc.data())
})
ところが、上記のコードをNode.jsで動かすとエラーになります。クライアントサイドで動かす分には問題ありません。
私はNuxt.jsを使っていて、mounted
で呼び出す時は問題ないのにasyncData
やfetch
にすると突然エラーになったのでかなり困りました。
このcustom Date objectが何なのかわからなかったのですが、とりあえずstartDateを出力してみると、
{
startDate: Mon Apr 01 2019 00:00:00 GMT+0900 (日本標準時)
}
{
startDate: 2019-03-31T15:00:00.000Z
}
表記が違う……?
Firestoreは前者の形なら正しく受け取ってくれますが、後者だとエラーになるようです。
唯一の救いは、両方に対応したTimestamp変換ツールがFirebaseのパッケージに含まれていること。
const startDate = firebase.firestore.Timestamp.fromDate(new Date(`2019/01/01 00:00:00`))
const endDate = firebase.firestore.Timestamp.fromDate(new Date(`2020/01/01 00:00:00`))
これなら動きます。
上記のコンソール表示では3/31 15:00になっていましたが、これはタイムゾーンの変換時の違いなので、Timestampに変換するとどちらも全く同じ時刻として扱われ、Firestoreから取ってくるだけなら何の問題もありません。
Node.jsの時刻の形式について直接問題視するような記事をあまり見かけなかったので、ひょっとすると片方でのみエラーを返すFirestoreの実装がおかしいのかもしれませが、解決したので深く考えるのは止めました。