The firestore UI allows me to create timestamp fields.
Saving objects with Date turns the date into string fields. Is it possible to save as timestamp fields? I assume these get optimized indices, and correct ordering.
You won't get a consistent server side timestamp with a JS date. Instead, send the server timestamp from the SDK.
const timestamp = firebase.firestore.FieldValue.serverTimestamp()
ref.update({ updatedAt: timestamp })
@codediodeio I'm not talking about server side timestamps, but datetimes in general.
@notsonotso JS Date objects do get saved as timestamps in Firestore. Are you sure you're not converting it to a string on your end?
ref.update({ updatedAt: new Date() })
// results in timestamp in Firestore
Wouldn't Date.now() provide easier querying?
https://stackoverflow.com/questions/47000854/firestore-query-by-date-range
I know I'm late to this but storing as UNIX timestamp makes for easy querying and ordering. Also, every language has support for UNIX timestamps.
Yeah I've just been using new Date() per docs and works fine.
Are any of you having problems reading the timestamp back from Firebase and displaying on angular? Whenever a javascript date is recorded into Firebase, once date is read back it comes as an incompatible object. Something like "Timestamp(seconds=1486443600, nanoseconds=0)" . This object is not compatible with Angular Date Pipes. Anybody knows how to deal with this?
@egalot just convert it to date .toDate() before your pipe.
@diginikkari Thank you!
@egalot I added toDate() and now shows the date in the correct format. But I get the following error in console: TypeError: Can not read property 'toDate' of undefined
Thanks @codediodeio this helped alot.
I was trying to add a new document to a collection with the server timestamp, so set() or update() was not a function I could run, since the document is not created yet.
Yes, I can create and then update which will work, but I wanted to prevent doing a double http call just to set the date.
I've found a solution, in case anyone else needs it:
// The object you want to add to the collection
let newDoc = {your: 'object'}
// Adding the server timestamp as finishedAt to the object
newDoc.finishedAt = firebase.firestore.FieldValue.serverTimestamp();
// Calling add()
this.someCollection.add(newDoc)
.then(ok)
.catch(error);
Is there a way to convert Date to Timestamp object ? As @kamran-mushtaq mentioned we get the following error in all the MaterialDatePickers which use ngModel for binding.
Okay, the only work around I was able to come up with is using a rxjs map operator and converting Timstamp to Date objects in my firestore observables. Thanks to @codediodeio for his amazing tutorials as always.
I had a problem with Firebase Storage timestamps vs Firestore timestamps. You can use this code to convert between them:
export function tryConvertFSTimestamp(obj: any) {
if (!obj || !obj._seconds)
return obj;
const millisec = obj._seconds * 1e3 + (obj._nanoseconds || 0) / 1e6;
return new Date(millisec).toISOString();
}
Here's a custom pipe to make your template code a little cleaner (includes Locale specific time)....
`import { formatDate } from '@angular/common';
import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core';
import { firestore } from 'firebase/app';
import Timestamp = firestore.Timestamp;
@Pipe({
name: 'firestoreDate'
})
export class FirestoreDatePipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private locale: string) {
}
transform(timestamp: Timestamp, format?: string): string {
return formatDate(timestamp.toDate(), format || 'medium', this.locale);
}
}`
This works for me: https://stackoverflow.com/a/58673212/1077309
I had a problem with Firebase Storage timestamps vs Firestore timestamps. You can use this code to convert between them:
export function tryConvertFSTimestamp(obj: any) { if (!obj || !obj._seconds) return obj; const millisec = obj._seconds * 1e3 + (obj._nanoseconds || 0) / 1e6; return new Date(millisec).toISOString(); }
Use Timestamp.toDate instead?
I'm saving properties of type Date in firestore and just after fetchting same javascript object, using the Angularfire collection, I do this:
fetchCompletedOrCancelledExercises(): Observable<Exercise[]> {
return (this.db.collection('finishedExercises') as AngularFirestoreCollection<Exercise>).valueChanges()
.pipe(
map( (exercises: Exercise[]) => {
return exercises.map(exercise => {
console.log(exercise);
return {
...exercise,
**endDate: ((exercise.endDate as unknown) as firebase.firestore.Timestamp).toDate(),**
};
})
})
);
every think after works fine in the rest of the aplication, and I don't have to call toDate() in the HTML template nor checking if the date property is a Timestamp or a Date object in TypeScript code.
@egalot just convert it to date .toDate() before your pipe.
This only works when the returned data is not serialized as JSON, e.g. return doc.data(). Is there a way where we can get the doc whose timestamp fields can be converted to JS Date before calling doc.data()? That would help the data binding and piping with AngularJS.
Most helpful comment
You won't get a consistent server side timestamp with a JS date. Instead, send the server timestamp from the SDK.