Reputation: 679
I´m currently running an Angular project with Firebase as a serverless backend.
There are two main models in the application user
and product
. Both of these models have several different timestamps such as createdAt
, updatedAt
, lastPurchase
, ...
interface User {
id: string;
displayName: string;
lastPurchase?: Date;
createdAt: Date;
updatedAt?: Date;
}
interface Product{
id: string;
title: string;
pricing: number;
category: string;
user: User;
createdAt: Date;
updatedAt?: Date;
}
The problem is that I´m working with the Date
type, but Firebase deliveres stored dates like this t {seconds: 1584540876, nanoseconds: 300000000}
.
Therefore, I´m forced to convert all incoming Firebase timestamps to JavaScript Date
types. Additionally, since Firebase´s Firestore is a NoSQL Database, I can never be certain which document contains which timestamp properties (for null checks).
This is the current working code I use when retrieving data from Firestore, but it is quite a mess.
// Iterate over all properties in product
for (let key in data) {
// Check if property is an object
if (data[key] instanceof Object) {
// Check if the object is Firebase Timestamp
if (data[key].constructor.name === 't') {
const property: string = key;
console.log(data[key]);
data[key] = data[property].toDate();
// Check if property is an user
} else if (key === 'user') {
// Iterate over all user properties
for (let userKey in data[key]) {
// Check if user property is an object and the object is Firebase Timestamp
if (data[key][userKey] instanceof Object && data[key][userKey].constructor.name === 't') {
const userProperty: string = userKey;
data[key][userKey] = data[key][userProperty].toDate();
}
}
}
}
}
Is there an alternative solution / method to achieve this with less computation?
Upvotes: 2
Views: 4355
Reputation:
I have struggled with the same problem and finally found this solution. set
interface User {
id: string;
displayName: string;
lastPurchase?: MyDate;
createdAt: MyDate;
updatedAt?: MyDate;
},
and next create class MyDate
export class MyDate {
seconds: number;
}
and in You code set this
<div>{{user.updatedAt.seconds * 1000 | date: 'MM/dd/yyyy'}}</div>
Upvotes: 0
Reputation: 161
When you want to display the date, simply use the date pipe of angular.
<div>{{user.updatedAt.toDate() | date: 'medium'}}</div>
Date pipe has other option like full, short also.
You can use firebase timestamps to store the date. You can use them like this:
import { firebase } from 'firebase/app';
import Timestamp = firestore.Timestamp;
interface User {
id: string;
displayName: string;
lastPurchase?: Timestamp;
createdAt: Timestamp;
updatedAt?: Timestamp;
}
Then, when you update them you can do so using now function:
User.update({
updatedAt: Timestamp.now();
})
This will save updatedAt at the time when you can the function to the update. You can similarly update createdAt and other dates.
Upvotes: 4