javascriptgoogle-cloud-firestoregoogle-cloud-functions

Problem with Firestore Timestamp and Google Cloud Functions (date.toDate() is not a function)


I am getting a date (from firestore) in a cloud function, and then returning it to the client side.

This is the resulted date object:

Object {
   "_nanoseconds": 1607618708,
   "_seconds": 615000000,
} // I know how to convert this to a javascript date object, but I need the .toDate()

Then, in the frontend, if I execute date.toDate() I get the error ".toDate is not a function".

In the other hand, if I get the same date from the client directly, all works perfectly... (.toDate() is a function)

This is the resulted date object:

t {
    "nanoseconds": 1607618708,
    "seconds": 615000000,
}

What is happening here? How can I solve this problem?

UPDATE

-> Code which doesn't work:

// Cloud Function
var userData = await firebase.getUserData(userId); // userRef.get().then(doc => ... return doc.data());
console.log(userData.birthday);
/*
    Timestamp {
       _seconds: 1038832012,
       _nanoseconds: 14000000 
    }
*/


return { userData }

// Client side

firebase.functions.httpsCallable(...)(...).then(res => {
    console.log(res.data.userData.birthday);
    /*
        Object {
           "_nanoseconds": 1607618708,
           "_seconds": 615000000,
        }

        new Date(date._seconds * 1000) will work but I need to execute .toDate()
    */
    const birthday = res.data.userData.birthday.toDate();
    // ERROR: .toDate is undefined
})...

-> Code which works (no server side):

 // Client side 
 const userData = await userRef.get().then((doc) => ... return doc.data());
 console.log(userData.birthday);
 /*
    t {
        "nanoseconds": 1607618708,
        "seconds": 615000000,
     } 
 */
 const birthday = userData.birthday.toDate(); // WORKS GOOD

Thank you.


Solution

  • Callable functions only serialize objects to JSON. When the SDK serializes a Timestamp, it merely takes its fields and constructs a new JSON object out of it. That object has no formal type. It is just a plain object with the two fields of data - seconds and nanoseconds - that it found inside the object.

    The client is going to receive that JSON with the two fields, but not necessarily know that it came from a Timestamp. You will have to write code on the client app to convert that JSON object with seconds and nanos back into a Timestamp, if that's what it want to use. Once you have seconds and nanos, you can simply create a new Timestamp with its constructor (new Timestamp(seconds, nanos)). Then you can call toDate() on that Timestamp. There is really no shortcut for this, except for you provide for yourself.