LukyFoggy
LukyFoggy

Reputation: 679

Angular Firebase retrieve Timestamps as Date

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

Answers (2)

user11202780
user11202780

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

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

Related Questions