AndreaNobili
AndreaNobili

Reputation: 43057

What is wrong in this Firestore timestamp into Date conversion in my Angular application?

I am working on an Angular project using FireStore database and I have the following problem:

Into my Firestore database a I have documents like this:

enter image description here

As you can see in the previous pic the start and end fields are defined on Firestore as TimeStamp fields.

Into a service class I retrieve all these documents in this collection and I return these documents as a list of Observable by this method:

getEvents(): Observable<any[]> {
    this.items = this.db.collection('calendar').valueChanges();

    return this.items;
 }

Then into the ngOnInit() method of my component class I do:

ngOnInit() {

    this.eventService.getEvents().subscribe(events => { this.events = events.map((event) => {

    console.log("START: ", event.start);
    //var date = new Date(event.start);
    var date = new Date(0); // The 0 there is the key, which sets the date to the epoch
    date.setUTCSeconds(event.start);

    var hour = date.getHours();

    console.log("START DATE: ", date);
    console.log("START HOUR: ", hour);
    // ...
}

and here my problem: the value of the event.start is not a date but an object like this (this is the console.log() output):

START:  t {seconds: 1487257200, nanoseconds: 0}

From what I know this object represents my date but how can I convert it again into a Date object.

As you can see I tried doing in this way:

var date = new Date(0); // The 0 there is the key, which sets the date to the epoch
date.setUTCSeconds(event.start);

but doing in this way I am obtaining a wrong date, in fact I am obtaining:

START DATE:  Sun Feb 16 3986 07:00:00 GMT-0800 (Ora standard del Pacifico USA)

the month and the day (Feb 16) are correct but the year is totally wrong (3986 instead 2017).

What is wrong? What am I missing? What is the correct way to obtain a Date object from the retrieved Firestore Timestamp?

Upvotes: 3

Views: 2294

Answers (3)

Mohamed Aljamil
Mohamed Aljamil

Reputation: 399

because firestore timestamp is actually different from normal JS Date().

in order to get JS date from timestamp you can use the method that firestore has on its timestamps.

in your code:

event.start should be event.start.toDate()

PS. for your IDE to know the methods that work on that object. Typescript must know the type of object it is. so for example if you are using AngularFire and you make a call to get a document then the type will already be there and your IDE will show available methods. But if the object type is generic like "any" then your IDE wont give available methods. and might throw an error like "method doesn't exist on type any"

Upvotes: 3

MauriceNino
MauriceNino

Reputation: 6757

You can use the Timestamps toDate() function and map the observable including arrays to Dates and return those objects:

// Create a custom type to tidy it up. Would recommend creating that in another file. 
// Here more on type aliases: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases

type ReturnType = {start: Date, end: Date, title: string};

// Change the function to return the created type

getEvents(): Observable<ReturnType[]> {
    this.items = this.db.collection('calendar').valueChanges()
        .pipe(map(tArr => // Use pipe to transform an observable or subject to something else, without subscribing. Check out: https://rxjs-dev.firebaseapp.com/guide/operators
            tArr.map(t => { // Map the array of objects including Timestamps to dates
                t.start = t.start.toDate();
                t.end = t.end.toDate();
                return t;
            })
        )) as Observable<ReturnType[]>;

    return this.items;
}

Upvotes: 2

Ilia Komarov
Ilia Komarov

Reputation: 633

You construct you JS Date incorrectly. Correct way to create date is passing milliseconds to it.

var date = new Date(event.start.seconds * 1000);

Upvotes: 1

Related Questions