Search code examples
node.jsgoogle-cloud-firestoremoment-timezone

Instable execution in firestore query using node moment in cloud function


The following code running OK in an function, but, strangely, in other function return error. Both functions using node 16 and run in the same project. Field in collection is timestamp.

...
const moment = require('moment-timezone');
...

var timeInit = moment.tz(new Date(), 'America/Sao_Paulo');
timeInit.startOf("day");

var timeEnd = moment.tz(await addDays (new Date(), 1), 'America/Sao_Paulo');
timeEnd.startOf("day");

const ref = db.collection("myCollection");
const snapshot = await ref.where('fieldtime', '>=', timeInit)
                          .where('fieldtime', '<', timeEnd)                   
                          .get();

Error: Argument "value" is not a valid FieldValue. Couldn't serialize object of type "Moment". Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the 'new' operator). at Object.exports. [as isFieldValue] (/workspace/node_modules/@google-cloud/firestore/build/src/validate.js:89:23) at CollectionReference.where (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:1096:18)

Edit 1: If I use .toDate(), as follow:

console.log("timeInit format ", timeInit.format('DD-MM-YYYY HH:mm:ss'));
console.log("timeEnd format ", timeEnd.format('DD-MM-YYYY HH:mm:ss'));

console.log("timeInit todate ", timeInit.toDate());
console.log("timeEnd todate ", timeEnd.toDate());

Console:

timeInit format 10-01-2022 00:00:00
timeEnd format 11-01-2022 00:00:00
timeInit todate  2022-01-10T03:00:00.000Z
timeEnd todate 2022-01-11T03:00:00.000Z

I' not lost the UTC-3?


Solution

  • The error message is:

    Couldn't serialize object of type "Moment"

    Firestore has its own internal Timestamp object for fields. When querying a Timestamp field, you can either specify a Timestamp as the value, or a Date object. But (as the error says) a Moment is neither a Timestamp or a Date, so it can't be used as the value for a query.

    From this question it seems you'll want to call toDate() on the Moment object to get a Date back: Moment.js transform to date object