1

This is in reference to this question Firebase Timestamp difference between current Timestamp and database timestamp error

If I use Timestamp.now() there are cases where the device clock is out of sync with Firestore and my time calculations are not accurate. I want to get the exact time from the Firestore server without being bothered by out of sync cases. Is there any way I could do that?

I have seen FieldValue.serverTimestamp() but there I cannot find a way to calculate anything using it, since it's return type is FieldValue and I am unable to parse it to Timestamp.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Maverick7
  • 1,087
  • 12
  • 22

2 Answers2

1

If you are using FieldValue.serverTimestamp() it means you let Firestore generate a timestamp for you. Please note that this timestamp is generated entirely on the server. It is not generated as document ids are, for instance on the client.

I cannot find a way to calculate anything using it since it's return type is FieldValue and I am unable to parse it to Timestamp.

When calling FieldValue's serverTimestamp() method, it true that type of the object that is returned is FieldValue but this only used to be passed as an argument when you need that timestamp property. Please check how you can add a timestamp to a Cloud Firestore document:

So if you query the database and you get a document that has a property that was set using FieldValue.serverTimestamp(), the type of object that is returned is Date. Since you get a Date object back, you can do whatever you want with it.

However, in Firebase Realtime Database we have another mechanism. So please see this answer:

So, in this case, it's totally different since we are using the time since the Unix epoch, in milliseconds and not a Date object.

Edit:

It sounds like your question started off about how to get a Timestamp from Firestore, but is actually just about how to structure a document so two devices can read the same document. However, to make it work, you should use two properties of type Date. One for device A and one for device B. Check the schema below:

Firestore-root
   |
   --- yourCollection (collection)
        |
        --- yourDocument (document)
              |
              --- deviceA: January 24, 2020 at 3:37:59 PM UTC+3 
              |
              --- deviceB: January 25, 2020 at 3:37:59 PM UTC+3 //Timestamp

To get the values of deviceA and deviceB properties, please use my answer from the following post:

Now you can compare both timestamps.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thanks @Alex Mamo, I also wanted the current server Timestamp in device B in a Date Object , so that I can compare it with the Timestamp stored in the database by device A. How can I achieve that? – Maverick7 Jan 25 '20 at 10:46
  • In that case, you should store a timestamp property in each document you need. For example, if device A reads a document with a particular timestamp and device B reads another document with another timestamp, then you can simply compare them. So both documents should store that property. – Alex Mamo Jan 25 '20 at 11:19
  • Device B reads the document stored by device A. There are no separate documents. But to understand whether the document read by device B is recent, I need to compare the timestamp from the document (that was set by Device A) and the timestamp generated by Device B when it read the document. In that case, I would need the server timestamp in device B. How can I achieve that? – Maverick7 Jan 25 '20 at 11:23
  • I think my comment was misunderstood. 2 devices are NOT reading the same document. As mentioned in my comment, device A is storing it and device B is reading it. I just need the server timestamp in device B, not from the document stored, but the Server Timestamp when Device B particularly read it. – Maverick7 Jan 25 '20 at 11:45
  • I think the [edited answer](https://stackoverflow.com/a/59908767/5246885) will help you understand better, right? – Alex Mamo Jan 25 '20 at 11:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/206636/discussion-between-maverick7-and-alex-mamo). – Maverick7 Jan 25 '20 at 15:13
1

One obvious but economically adverse way is to write to Firestore Database, the timestamp and read it again from there.

db.collection("TimestampChecker").document("some_string").set(new TimestampGetter()).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {

            db.collection("TimestampChecker").document("some_string").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    if(task.getResult()!=null)
                    {
                        TimestampGetter timestampGetter = task.getResult().toObject(TimestampGetter.class);
                        Date dateNow = timestampGetter.getTimestampNow();

                    }

                }
            });

        }
    });

And TimestampGetter can be a class like this:

public class TimestampGetter {
@ServerTimestamp
private Date timestampNow;

public TimestampGetter(Date timestampNow) {
    this.timestampNow = timestampNow;
}

public TimestampGetter() {
}

public Date getTimestampNow() {
    return timestampNow;
}

public void setTimestampNow(Date timestampNow) {
    this.timestampNow = timestampNow;
}}
Maverick7
  • 1,087
  • 12
  • 22