How to set epoch in Firestore using server time - android

I'm trying to set the epoch when data is created in Firestore. I'm looking to get some similar result to what is done in the real-time database, using ServerValue.TIMESTAMP.
I don't want to set it by using the device time System.getCurrentMillis because that time can be changed by the user.
According to docs an update needs to be done, the problem with that is the format. This is my code:
Map<String, Object> map = new HashMap<>();
map.put("timestamp", FieldValue.serverTimestamp());
reference.update(map);
And this is the result in the Firebase web console:
I was very surprised it is in spanish, which could be useful in some situations but epoch is what I'm chasing. Try to see the bright side and stick with it and thought that I was seeing the web in spanish, so I changed the language in the footer selector, it didn't change. On this point I'm assuming is set in the project language.
Back to the epoch attempt. Considering my project is using the real-time database as well, I try to set it in that way:
Map<String, Object> map = new HashMap<>();
map.put("timestamp", ServerValue.TIMESTAMP);
reference.update(map);
It did upload something, but it was just nonsense.
I think using epoch as the server-side timestamp is a better standard approach, after that every client can transform it to the user convenience and locale.
Can the epoch by set as server value in Firestore?
UPDATE
The answer marked as correct lead me to some interesting findings that I would like to share, so others in the same situation can benefit from:
There is no need to set the epoch because of the FieldValue.serverTimestamp() it is a date object handled by the database, what we see in the console is just a friendly way to show it.
Since FieldValue.serverTimestamp() is a date object it can be sort as any other timestamp could be, if you add orderBy("timestamp", Query.Direction.DESCENDING) to your query (or Query.Direction.ASCENDING) it will sort the results correctly.
And regarding to a the #34m0 comment, that is right, clients should not take care of the logic for setting the creation time, but it should be done in Functions.

The object that results from setting a Firestore field with FieldValue.serverTimestamp() is an instance of java.util.Date. When you later read the value, you can get the epoch time using getTime().
As an example, for a document created like this:
Map<String, Object> doc = new HashMap<>();
doc.put("timestamp", FieldValue.serverTimestamp());
The resulting value can be read like this:
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot snapshot = task.getResult();
if (snapshot != null) {
Map<String,Object> map = snapshot.getData();
Date date = (Date) map.get("timestamp");
Log.d(TAG, "date=" + date);
Log.d(TAG, "time=" + date.getTime());
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get() failed with ", task.getException());
}
}
});

Related

Get specific data from Firestore and convert it to string, int, ... variables

I'm creating this post as I can't solve my problem with existing ones.
I'm saving the current time on Firestore with :
Map<String, Object> docData = new HashMap<>();
docData.put("Starting date", new Timestamp(new Date()).toDate());
docData.put("Quantification", 3.14569);
userManager.getUsersCollection().document(userManager.getCurrentUser().getUid())
.collection("habits")
.document(selectedHabit)
.set(docData)
Then, I would like to get back the timestamp and use it to count since how many days it's been created. I'm stuck here. The only way I found to access specific data of a document is by doing this :
userManager.getLoggedUserHabitsSubCollection()
.get()
.addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {#
Override
public void onComplete(#NonNull Task < QuerySnapshot > task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document: task.getResult()) {
Log.d("test", document.getId() + " => " + document.getData() + " => " + document.get("Starting date"));
}
} else {}
}
});
with "document.get("Starting date") I can access my saved date, that's the only thing that I was able to make work to do so. Now I would like to be able to display this Object in a string, and to check differences between dates to know how much time have passed. And here I'm stuck. I see a lot of different answers on forums, like using .toDate() for example, but when I write document.getData().toDate(), it's in red. I tried a lot of things with different ways of writing it, it's always in red and I can't make it work. Any help appreciated.
I see a lot of different answers on forums, like using .toDate() for example, but when I write document.getData().toDate(), it's in red.
DocumentSnapshot#getData() method returns an object of type Map<String, Object>. So there is no way you can add a call to .toDate() on such an object. If you need to get the value of a specific field as a Date object, then you should use the getDate(String field) method, which:
Returns the value of the field as a Date.
Or DocumentSnapshot#getTimestamp(String field) method which:
Returns the value of the field as a com.google.firebase.Timestamp.
Once you have the Date object, you can then calculate the difference between two Java date instances.

Get current server Date and Time in Firebase Firestore

I want to get my server time in Firebase Firestore so I can use it for my countdown logic. I can't find anywhere and mostly they suggest to use FiedValue.serverTimeStamp or ServerValue.TIMESTAMP which is both are used to save data. I don't want to save data I just want to get the server time.
Is there a static way like FirebaseFirestore.getInstance().getServerTime()?
There is no provided method to get the actual server time.
Server timestamps are just token values on the client that are give a final value when they reach Firestore. The best you can do is write a server timestamp to a field in a document, then read the doucument back from Firestore after field has a value. Bear in mind that the timestamp will be "late" at that point, because of the time it takes your code to actually write and read the data. You have no guarantee how long that process will take.
For a more details explanation of how server timestamps work, read this article.
As per said by the #Doug there is no way of getting just only time from Firebase. However there are many round-ways for the same.
Firstly, you can use the count-down using the device of the app user since all the time in today era is synced with satellite. This can be done using:
Date dateStart = new Date();
Date dateEnd = new Date();
System.out.println(dateEnd.getTime() - dateStart.getTime()/1000);
Secondly, create an object in firebase for the starting time (for particular user) and then when the countdown is over then count the difference between the current time and the time uploaded in database.
FirebaseFirestore db = FirebaseFirestore.getInstance();
// At the time of setting.
Map<String, Object> map= new HashMap<>();
map.put("startTime", (new Date()).getTime());
db.collection(userdata).document(userid).set(map);
// At the time of retrieving:
db.collection(userdata).document(userid).get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
// Here you can get the time..
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
Now if you don't like any of the above method then you can file a support request for time at https://firebase.google.com/support

Get all Firestore documents after specific date

What I try to accomplish is the following: I have a collection where documents get added with a timestamp in them. I then want to listen to that collection via snapshotlistener, but just for new documents. So I update my timestamp to the newest document-timestamp received, and try to query only the documents newer than my timestamp. In onCreate I assign lastUpdateTime a date in the past, so that I get the first document added.
val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.US)
try {
lastUpdateTime = sdf.parse("01/01/2000")
} catch (e: ParseException) {
//
}
then I add the snapshotlistener and try to update lastUpdateTime in order to just look for documents newer than thist Date/Time
val path = //...path to my collection
private var lastUpdateTime = Any() //my up-to-date timestamp. I first assign it some date in the past, to make sure it gets the first document added.
// some code
talksListener = path.whereGreaterThan("timestamp", lastUpdateTime)
.addSnapshotListener(EventListener<QuerySnapshot> { snapshot, e ->
if (snapshot != null && !snapshot.isEmpty && !snapshot.metadata.hasPendingWrites()) {
for (dSnapshot in snapshot) {
val thisTimestamp = dSnapshot.get("timestamp")
if (thisTimestamp != null) {
lastUpdateTime = thisTimestamp
}
}
}
})
But every time I add an document, I get the whole collection again.
I also tried all combinations with orderBy and startAt/endAt/startBefore/EndBefore but the result is the same. Either I get nothing, or the whole collection every time a new document is added.
for example:
talksListener = path.orderBy("timestamp").startAfter(lastUpdateTime)
Where is the problem here?
Also, on a different note, is there a possibility to include !snapshot.metadata.hasPendingWrites() into the query in Kotlin. The documentation says to use MetadataChanges.INCLUDE but I do not get how to implement it in Kotlin. Every Hint is much appreciated.
edit 1:
My firestore DB is structured like this:
users/{user}/messages/{message} -> here is the timestamp located
and my path leads to ./messages
edit 2:
the solution is to detach and reattach the listener after the new lastUpdateTime is assigned. That does not sound good to me, so if anyone has a better solution, I am happy to hear it. For the time being I will stick to it though.

Collect the exact time when a specific data has been updated in Firebase via Android Studio

May I ask if there is any implementation to collect the time when the first data is updated. For example, there is a queue function in my app. When an user has taken the queue ticket, Firebase will then be updated.
Therefore, I would like to know the time that the first user in the queue.
Is there any code for this in Android Studio? Many thanks!!
The Firebase Database does not store metadata (informations like the timestamp) for CRUD operations that are performed. Because of that, you need to store this kind of data yourself by creating your own mechanism.
In fact, you need to create a new field for each child you want to trace and change the value of the timestamp every time a action is performed. The best practice within a Firebase database is to save your data as a timestamp using: ServerValue.TIMESTAMP.
Note, that when you are saving the timestamp, you are saving as a Map and when you are retrieving, you are retrieving it as a long.
To set the timestamp, I recommend you to use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Map<String, Object> map = new HashMap<>();
map.put("timestamp", ServerValue.TIMESTAMP);
rootRef.child("yourNode").updateChildren(map);
To get you data back, I recommend you using the following method:
public static String getTimeDate(long timeStamp){
try{
DateFormat dateFormat = getDateTimeInstance();
Date netDate = (new Date(timeStamp));
return dateFormat.format(netDate);
} catch(Exception e) {
return "date";
}
}

How to delete firebase items that are "expired" or past the current date on Android Studio?

Hello I am creating an Android app that lists local events happening around my campus. Each "event" has children for storing the title, image, category, info, and date. I was wondering what the best way would be to delete events that are past the current date. The date is formatted mm/dd/yy. I don't have much experience with using date functions in Java, and could use some advice.
Here is an example of an event. Here is the source code for reference. Any help is greatly appreciated.
The best practice is to save your data as a TIMESTAMP like this ServerValue.TIMESTAMP.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Map<String, Object> map = new HashMap<>();
map.put("time", ServerValue.TIMESTAMP);
ref.child("yourNode").updateChildren(map);
And to get the data back, i suggest you use this method:
public static String getTimeDate(long timeStamp){
try{
DateFormat dateFormat = getDateTimeInstance();
Date netDate = (new Date(timeStamp));
return dateFormat.format(netDate);
} catch(Exception e) {
return "date";
}
}
To solve your problem, you only need get the date from your database and compare it with the current date and time. If the value of TIMESTAMP is less than the current date and time, than you can delete that particular event.
Hope it helps.
You can filter the fire base response on date itself
ex:
DatabaseReference mDatabaseReference =FirebaseDatabase.getInstance().getReference().child("table name");
ref.orderByChild("date").startAt(startDate).endAt(endDate).on("child_added", function(snapshot){
console.log("got the data!", snapshot);
});

Categories

Resources