Firestore dates written as strings, not Timestamps

Any updates on this one? I have an existing date that I don’t want changed in any way. I want FireStore to continue to see it as type Timestamp. Thanks!

Hello Retool Team!

Poking my head up here to see if there are solutions around this coming down the pike.

Thank you,
Brett

Any news on this? This bit us hard on a week we were supposed to go live.

The value will be stored as a Firebase timestamp if you send it a date object, here is an example using moment:


Hey @ben thanks for the information. Yes, I know about this workaround, the biggest issue is that is is really rare that the date is the only thing being updated, most often it is an entire object being sent to be added or updated, which gets stringified and the date is stored as a string. There is currently know way to get the date as a Date when it's part of an object.

I just thought of this (and not thought through at all), but how about an option to JSON.parse a value being used or the ability to pass it through a transformer first? I am sure there are caveats there too.

Thank you,

Brett

Sorry for the delay!

The issue is that we stringify the items passed into the additionalScope, and that even when you JSON.parse() on the other side (in this case within the Firebase query), the value does not get converted back into a Moment object (it's just trying to parse a string). Instead, we have to use Moment within the Firebase query again, to convert the string into an object again.

So if we have our JS query:

Then within our Firebase query, we parse it back to an object:

Which then gets stored in FB as a Timestamp!

Plausible approach, yes, Thank You. Very manual though and error prone as you have to remember to update the firestore query when you update the javascript query. And there is no reuse of firestore queries.

If it could go through some type of transformer first it could remove the manual updates of any field, and only those of Date fields would need to be added/adjusted for. For example:

const lastUpdatedAt = data.recordUpdates.lastUpdatedAt;

return {
  ...data.recordUpdate,
  moment: moment(data.recordUpdates.lastUpdatedAt),
}
1 Like

This solution won't work for an array of dates from a transformer. eg:

I've tried using an external library to 'moment' the dates:
image

When i use the function in the value field of the, which appears correct in the preview box, but writes null to the DB.

image

Are you able to provide a clearer example, I cannot read what is there. Thank you.

Thanks for looking into it, I updated the message above with more details.

Oh, this is a tough one. Based on what you have I would expect item to be an array of map field types which has two elements each named date, with the string value of a date. Since both maps use a key value of date, I am assuming the write fails and that is why it's null (or something like that).

You are trying to write:

item: [
  {
    date: '2022-03-10T17:35:39.165Z'
  },
  {
    date: 'e0ee-03-10T17:35:39.165Z
  }
]

This is invalid for Firestore to store as both map types have the same key value. Try adding a manual document in Firestore and you'll see.

How do you want the data to be in Firestore? We'll start with this and see how we can construct it in Retool so you can get the data written and with Firestore Timestamp types.

Thanks for looking into it. I changed the array to:
image

and the function to
image

The preview and run works:

The DB is updated but with a null for the items.
image

Based on the json value in the preview that looks valid. We would need to see how all the pieces are put together to determine why Firestore is saving a null in this case.

1 Like

Thanks for checking. It appears Retool is converting dates into strings when passed between transformers / scripts, that should be classified as a bug right?

I am pretty sure it is listed already, it is the basis around this entire forum thread. There are some work-arounds listed here, though they are a bit of a pain to deal with.

Hi guys, still struggling with this problem on my side, tell me how dynamically prepare a field with moment? For instance I have a json where names of fields with timestamp could be different, so I iterate them and prepare json, but on my end it does not work throws this: Unexpected token 'F', "Failed to "... is not valid JSON, tell me how could I achieve that?

This is my example:

(function(){
  const initialValue = CollectionItemJSONEditorCreate.value;
  const fieldsToProcessAsTimeStamp = timestampFields.value.split(',');
  const result = Object.keys(initialValue).reduce((aggr, next) => {
    if (fieldsToProcessAsTimeStamp.includes(next)) {
      aggr[next] = moment(initialValue[next]);
    }
    return aggr;
  }, {});
  return {...initialValue, ...result};
})()
}}

Hi @Oleksandr_Tserkovnyi. Where are you running that function at? I am not sure I understand what it's doing as well.

Hello!

Is there a plausible solution for this?

I have a rather simple scenario that is not working.
I have an array with Dates and I want to write them back to firestore. I have tried 3 different approaches:

1:
image
Result:
image

2:
image
Result:


(...)

3:
image

Result:
image

The strange part is that if I do this:
image

it works as I wanted: (although I lost all my data...)
image

Any ideas for this?

Thank you!

The reason 1, 2, & 3 are not working is that you are sending back an array of dates, which are all stringified as they are sent to the Firestore resource in Retool then sent to Firestore as a string. I am not sure about the one that worked as in my experience that would usually end up as a string as well. Perhaps there was a Retool update which handles the moment object in a special manor.

To the best of my knowledge this is no way to handle this other than constructing the array of dates from within the Firestore resource you are using to update firestore as anything passed from a JavaScript query, etc. will be stringified first.

Thank you for the quick answer!

I am actually doing everything directly in the resource that updates firestore:

1 Like