Vicky Thakor
Vicky Thakor

Reputation: 3916

Add timestamp in Firestore documents

I'm newbie to Firestore. Firestore docs says...

Important: Unlike "push IDs" in the Firebase Realtime Database, Cloud Firestore auto-generated IDs do not provide any automatic ordering. If you want to be able to order your documents by creation date, you should store a timestamp as a field in the documents.

Reference: https://firebase.google.com/docs/firestore/manage-data/add-data

So do I have to create key name as timestamp in document? Or created is suffice to fulfill above statement from Firestore documentation.

{
    "created": 1534183990,
    "modified": 1534183990,
    "timestamp":1534183990
}

Upvotes: 72

Views: 114182

Answers (19)

Tim Erickson
Tim Erickson

Reputation: 592

You can call it whatever you want! But figuring out the syntax—which changes with each new version, it seems—can be a pain.

This works for me in late 2024, in JavaScript, modular scheme...:

import * as FB from "https://www.gstatic.com/firebasejs/11.0.2/firebase-firestore.js";

export async function saveGeorge() {
    const theCR = FB.collection(db, "myTable");   // collection reference
    const theData = {
       first : "George",
       last : "Washington",
       created : FB.Timestamp.now()  // here is the time
    }
    const docRef = await FB.addDoc(theCR, theData);
}

Using Timestamp.now() produces a time that shows up correctly in the dashboard, complete with my local time zone—but may depend on my local server's clock.

For me, using FB.serverTimestamp() gave exactly the same result.

Upvotes: 0

Bastian Valencia
Bastian Valencia

Reputation: 1

in flutter:

final docData = {
  "stringExample": "Hello world!",
  "booleanExample": true,
  "numberExample": 3.14159265,
  "dateExample": Timestamp.now(),  <------
  "listExample": [1, 2, 3],
  "nullExample": null
};

Upvotes: 0

LuscaDev
LuscaDev

Reputation: 359

In the version 9 just use the following import.

import { Timestamp } from '@angular/fire/firestore'

Your code will look like this:

ref.child(key).set({
  id: itemId,
  content: itemContent,
  user: uid,
  createdAt: Timestamp.fromDate(new Date())
})

Upvotes: 1

Cristian Muscalu
Cristian Muscalu

Reputation: 9925

Sharing what worked for me after googling for 2 hours, for firebase 9+

import { serverTimestamp } from "firebase/firestore";

export const postData = ({ name, points }: any) => {
  const scoresRef = collection(db, "scores");
  return addDoc(scoresRef, {
    name,
    points
    date: serverTimestamp(),
  });
};

Upvotes: 1

Moumen Lahmidi
Moumen Lahmidi

Reputation: 482

The newest version from Firestore you should use it as follow

import { doc, setDoc, Timestamp } from "firebase/firestore"; 

const docData = {
    ...
    dateExample: Timestamp.fromDate(new Date("December 10, 1815"))
};
await setDoc(doc(db, "data", "one"), docData);

or for sever timestamp

import { updateDoc, serverTimestamp } from "firebase/firestore";

const docRef = doc(db, 'objects', 'some-id');

const updateTimestamp = await updateDoc(docRef, {
   timestamp: serverTimestamp()
});

Upvotes: -1

Green
Green

Reputation: 1761

According to the docs, you can "set a field in your document to a server timestamp which tracks when the server receives the update".

Example:

import { updateDoc, serverTimestamp } from "firebase/firestore";

const docRef = doc(db, 'objects', 'some-id');

// Update the timestamp field with the value from the server
const updateTimestamp = await updateDoc(docRef, {
    timestamp: serverTimestamp() // this does the trick!
});

Upvotes: 1

uɥƃnɐʌuop
uɥƃnɐʌuop

Reputation: 15153

That's correct, like most database, Firestore doesn't store creation times. In order to sort objects by time:

Option 1: Create timestamp on client (correctness not guaranteed):

db.collection("messages").doc().set({
  ....
  createdAt: firebase.firestore.Timestamp.now()
})

The big caveat here is that Timestamp.now()uses the local machine time. Therefore, if this is run on a client machine, you have no guarantee the timestamp is accurate. If you're setting this on the server or if guaranteed order isn't so important, it might be fine.

Option 2: Use a timestamp sentinel:

db.collection("messages").doc().set({
  ....
  createdAt: firebase.firestore.FieldValue.serverTimestamp()
})

A timestamp sentinel is a token that tells the firestore server to set the time server side on first write.

If you read the sentinel before it is written (e.g., in a listener) it will be NULL unless you read the document like this:

doc.data({ serverTimestamps: 'estimate' })

Set up your query with something like this:

// quick and dirty way, but uses local machine time
const midnight = new Date(firebase.firestore.Timestamp.now().toDate().setHours(0, 0, 0, 0));

const todaysMessages = firebase
  .firestore()
  .collection(`users/${user.id}/messages`)
  .orderBy('createdAt', 'desc')
  .where('createdAt', '>=', midnight);

Note that this query uses the local machine time (Timestamp.now()). If it's really important that your app uses the correct time on the clients, you could utilize this feature of Firebase's Realtime Database:

const serverTimeOffset = (await firebase.database().ref('/.info/serverTimeOffset').once('value')).val();
const midnightServerMilliseconds = new Date(serverTimeOffset + Date.now()).setHours(0, 0, 0, 0);
const midnightServer = new Date(midnightServerMilliseconds);

Upvotes: 13

GorvGoyl
GorvGoyl

Reputation: 49570

multiple ways to store time in Firestore

  1. firebaseAdmin.firestore.FieldValue.serverTimestamp() method. The actual timestamp will be computed when the doc is written to the Firestore.
    while storing it looks like this:

enter image description here

  1. firebaseAdmin.firestore.Timestamp.now() method.
    while storing it looks like this:

enter image description here

For both the methods, next time you fetch data it will return Firestore Timestamp object:

enter image description here

So, you first need to convert it to native js Date object and then you can perform methods on it like toISOString().

export function FStimestampToDate(
  timestamp:
    | FirebaseFirestore.Timestamp
    | FirebaseFirestore.FieldValue
): Date {
  return (timestamp as FirebaseFirestore.Timestamp).toDate();
}
  1. Store as unix timestamp Date.now, it'll be stored as number i.e. 1627235565028 but you won't be able to see it as readable Date in firestore db.
    To query on this Firestore field, you need to convert the date to timestamp and then query.

  2. Store as new Date().toISOString() i.e. "2021-07-25T17:56:40.373Z" but you won't be able to perform date range query on this.

I prefer the 2nd or 3rd way.

Upvotes: 0

John Yepthomi
John Yepthomi

Reputation: 502

REALTIME SERVER TIMESTAMP USING FIRESTORE

import firebase from "firebase/app";

const someFunctionToUploadProduct = () => {

       firebase.firestore().collection("products").add({
                name: name,
                price : price,
                color : color,
                weight :weight,
                size : size,
                createdAt : firebase.firestore.FieldValue.serverTimestamp()
            })
            .then(function(docRef) {
                console.log("Document written with ID: ", docRef.id);
            })
            .catch(function(error) {
                console.error("Error adding document: ", error);
            });

}

All you need is to import 'firebase' and then call firebase.firestore.FieldValue.serverTimestamp() wherever you need it. Be careful with the spelling though, its "serverTimestamp()". In this example it provides the timestamp value to 'createdAt' when uploading to the firestore's product's collection.

Upvotes: 12

Firestone method does not work. Use Timestamp from java.sql.Timestamp and don't cast to string.. Then firestone formats it properly. For example to mark a now() use:

val timestamp = Timestamp(System.currentTimeMillis())

Upvotes: 0

Saccarab
Saccarab

Reputation: 1521

firebase.firestore.FieldValue.serverTimestamp()

Whatever you want to call it is fine afaik. Then you can use orderByChild('created').

I also mostly use firebase.database.ServerValue.TIMESTAMP when setting time

ref.child(key).set({
  id: itemId,
  content: itemContent,
  user: uid,
  created: firebase.database.ServerValue.TIMESTAMP 
})

Upvotes: 75

Cesar
Cesar

Reputation: 91

I am using Firestore to store data that comes from a Raspberry PI with Python. The pipeline is like this:

Raspberry PI (Python using paho-mqtt) -> Google Cloud IoT -> Google Cloud Pub/Sub -> Firebase Functions -> Firestore.

Data in the device is a Python Dictionary. I convert that to JSON. The problem I had was that paho-mqtt will only send (publish) data as String and one of the fields of my data is timestamp. This timestamp is saved from the device because it accurately says when the measurement was taken regardless on when the data is ultimately stored in the database.

When I send my JSON structure, Firestore will store my field 'timestamp' as String. This is not convenient. So here is the solution.

I do a conversion in the Cloud Function that is triggered by the Pub/Sub to write into Firestore using Moment library to convert.

Note: I am getting the timestamp in python with:

currenttime = datetime.datetime.utcnow()

var moment = require('moment'); // require Moment 
function toTimestamp(strDate){
  return parsedTime = moment(strDate, "YYYY-MM-DD HH:mm:ss:SS");
 }

exports.myFunctionPubSub = functions.pubsub.topic('my-topic-name').onPublish((message, context) => {

  let parsedMessage = null;
  try {
    parsedMessage = message.json;

    // Convert timestamp string to timestamp object
    parsedMessage.date = toTimestamp(parsedMessage.date);

    // Get the Device ID from the message. Useful when you have multiple IoT devices
    deviceID = parsedMessage._deviceID;

    let addDoc = db.collection('MyDevices')
                    .doc(deviceID)
                    .collection('DeviceData')
                    .add(parsedMessage)
                    .then ( (ref) => {
                      console.log('Added document ID: ', ref.id);
                      return null;
                    }).catch ( (error) => {
                      console.error('Failed to write database', error);
                      return null;
                    });

  } catch (e) {
    console.error('PubSub message was not JSON', e);
  } 

  // // Expected return or a warning will be triggered in the Firebase Function logs.
  return null;  
});

Upvotes: 0

Marcel
Marcel

Reputation: 173

This solution worked for me:

Firestore.instance.collection("collectionName").add({'created': Timestamp.now()});

The result in Cloud Firestore is: Cloud Firestore Result

Upvotes: 2

johnson lai
johnson lai

Reputation: 1036

Use firestore Timestamp class, firebase.firestore.Timestamp.now().

Since firebase.firestore.FieldValue.serverTimestamp() does not work with add method from firestore. Reference

Upvotes: 57

Venkat Kotra
Venkat Kotra

Reputation: 10753

For Firestore

ref.doc(key).set({
  created: firebase.firestore.FieldValue.serverTimestamp()
})

Upvotes: 10

Stephane Paquet
Stephane Paquet

Reputation: 2344

Swift 5.1

...
"dateExample": Timestamp(date: Date()),
...

Upvotes: -1

Bishoy Hanna
Bishoy Hanna

Reputation: 4589

The way it worked with me, is just taking the timestamp from the snapshot parameter snapshot.updateTime

exports.newUserCreated = functions.firestore.document('users/{userId}').onCreate(async (snapshot, context) => {
console.log('started!     v1.7');
const userID = context.params['userId'];

firestore.collection(`users/${userID}/lists`).add({
    'created_time': snapshot.updateTime,
    'name':'Products I ♥',
}).then(documentReference => {
    console.log("initial public list created");
    return null;
  }).catch(error => {
    console.error('Error creating initial list', error);
    process.exit(1);
});

});

Upvotes: 1

coders
coders

Reputation: 2477

Try this one for Swift 4 Timestamp(date: Date())

let docData: [String: Any] = [
"stringExample": "Hello world!",
"booleanExample": true,
"numberExample": 3.14159265,
"dateExample": Timestamp(Date()),
"arrayExample": [5, true, "hello"],
"nullExample": NSNull(),
"objectExample": [
    "a": 5,
    "b": [
        "nested": "foo"
    ]
]
]
db.collection("data").document("one").setData(docData) { err in
if let err = err {
    print("Error writing document: \(err)")
} else {
    print("Document successfully written!")
}
}

Upvotes: 1

Doug Stevenson
Doug Stevenson

Reputation: 317798

The documentation isn't suggesting the names of any of your fields. The part you're quoting is just saying two things:

  1. The automatically generated document IDs for Firestore don't have a natural time-based ordering like they did in Realtime Database.
  2. If you want time-based ordering, store a timestamp in the document, and use that to order your queries. (You can call it whatever you want.)

Upvotes: 2

Related Questions