React - display a firestore timestamp

后端 未结 6 2052
醉酒成梦
醉酒成梦 2020-12-18 22:38

I am trying to figure out how to display a firestore timestamp in a react app.

I have a firestore document with a field named createdAt.

I am trying to inc

相关标签:
6条回答
  • 2020-12-18 23:22

    When you get timestamps from Firestore they are of the following type:

    To convert this into a normal timestamp you can use the .toDate() function.

    For example, for a document like the following:

    We can use something like:

    db.collection('[COLLECTION]').doc('[DOCUMENT]').get().then(function(doc) {
      console.log(doc.data().[FIELD].toDate());
    });
    

    and the output will be like:

    2019-12-16T16:27:33.031Z
    

    Now to process that timestamp further, you can convert it into a string and use regex to modify it according to your needs.

    For example: (I'm using Node.js here)

    db.collection('[COLLECTION]').doc('[DOCUMENT]').get().then(function(doc) {
      var stringified = doc.data().[FIELD].toDate().toISOString();
      //console.log(stringified);
      var split1 = stringified.split('T');
      var date = split1[0].replace(/\-/g, ' ');
      console.log(date);
      var time = split1[1].split('.');
      console.log(time[0]);
    });
    

    Will give you an output like this:

    0 讨论(0)
  • 2020-12-18 23:32

    With a document ID of a User that does have the createdAt property set, try the following:

    const docRef = db.collection("users").doc("[docID]");
    
    docRef.get().then(function(docRef) {
      if (docRef.exists) {
         console.log("user created at:", docRef.data().createdAt.toDate());
      }
    })
    

    I'ts important to call the .data() method before accessing the document's properties

    Note that if you access docRef.data().createdAt.toDate() of a user for which the createdAt propery is not set, you will get TypeError: Cannot read property 'toDate' of undefined

    So in case you have any user in your collection that has no createdAt property defined. You should implement a logic to check if the user has the createdAt property before getting it. You can do something like this:

    //This code gets all the users and logs it's creation date in the console
    docRef.get().then(function(docRef) {
      if (docRef.exists && docRef.data().createdAt) {
          console.log("User created at:", docRef.data().createdAt.toDate());
      }
    })
    
    0 讨论(0)
  • 2020-12-18 23:34

    How to send the date to Firestore:

    import firebase from 'firebase/app';
    
    // ..........
    // someObject is the object you're saving to your Firestore.
    
    someObject.createdAt: firebase.firestore.Timestamp.fromDate(new Date())
    

    How to read it back:

    function mapMonth(monthIndex) {
      const months = {
        0: 'jan',
        1: 'feb',
        2: 'mar',
        3: 'apr',
        4: 'may',
        5: 'jun',
        6: 'jul',
        7: 'aug',
        8: 'sep',
        9: 'oct',
        10: 'nov',
        11: 'dec'
      };
      return months[monthIndex];
    }
    
    // ..........
    // Here you already read the object from Firestore and send its properties as props to this component.
    
    return(
        <LS.PostDate_DIV>
          Published on {mapMonth(props.createdAt.toDate().getMonth()) + ' '}
          of {props.createdAt.toDate().getFullYear()}
        </LS.PostDate_DIV>
      );
    }
    

    Basically when you do createdAt.toDate() you get a JS Date object.

    I use it like this all the time!

    From: https://cloud.google.com/firestore/docs/manage-data/add-data

    This will create a data based on the user's system date. If you need to be sure that everything will be stored chronologically (without any errors of wrong system dates set by your users system) on your DB, you should use a server timestamp. The date will be set using your Firestore DB internal date system.

    0 讨论(0)
  • 2020-12-18 23:36

    I've encountered problems in the past with nested object properties not rendering properly in lists where item.someProp is considered an object, but item.someProp.someSubProp won't resolve with the value of someSubProp in item.someProp.

    So to skirt around the issue, why not evaluate Timestamp to a plain date object (or the desired display format) when creating the user object?

    this.unsubscribe = this.props.firebase
      .users()
      .onSnapshot(snapshot => {
        let users = [];
    
        snapshot.forEach(doc =>
          let docData = doc.data();
          docData.createdAt = docData.createdAt.toDate();
          users.push({ ...docData, uid: doc.id }),
        );
    
        this.setState({
          users,
          loading: false,
        });
      });
    
    0 讨论(0)
  • 2020-12-18 23:41

    After some discussion, we found that the time stamps in OPs user object could be renders as such:

    render() { 
    const { users, loading } = this.state; 
    
    return ( 
        <div> 
            {loading && <div>Loading ...</div>} 
    
            {users.map(user => ( 
    
                <Paragraph key={user.uid}> 
    
                    <key={user.uid}> 
                        {user.email} 
                        {user.name} 
                        {new Date(user.createdAt.seconds * 1000).toLocaleDateString("en-US")}
    

    I recreated your example in a dummy React project, and received the same error as expected.

    Error: Objects are not valid as a React child

    I was able to get this to render correctly with the following method, which should also work for you:

    {new Date(user.createdAt._seconds * 1000).toLocaleDateString("en-US")}
    

    Which, for my sample timestamp, rendered as:

    12/30/2019


    Be sure you are using a timestamp that was saved to Firestore as:

    createdAt: this.props.firebase.Timestamp.fromDate(new Date())
    

    Note: This is assuming that your instance of firebase.firestore() is at this.props.firebase. In other examples you use this.props.firebase, but those methods look like helper methods that you have created yourself.

    When this value is fetched, it will be an object with two properties -- _seconds and _nanoseconds.

    Be sure to include the underscore. If you use createdAt.seconds it won't work, it must be createdAt._seconds.


    Other things I tried:

    user.createdAt.toDate() throws toDate() is not a function.

    user.createdAt throws Error: Objects are not valid as a React child

    new Date(user.createdAt._nanoseconds) renders the wrong date

    0 讨论(0)
  • 2020-12-18 23:41

    So firestore stores dates as an object with seconds and nanoseconds. If you want the time the user was created then you would reference user.createdAt.nanoseconds. This returns a unix timestamp.

    How do you want to display date into in your app? If you want to get a date object then you can pass the timestamp into a date constructor like so new Date(user.createdAt.nanoseconds). Personally I enjoy using the date-fns library for handling time.

    0 讨论(0)
提交回复
热议问题