【问题标题】:How to use end datetime in Firebase Realtime Database如何在 Firebase 实时数据库中使用结束日期时间
【发布时间】:2018-04-20 00:54:31
【问题描述】:

在我们的应用中,保存新数据的结束日期时间非常重要。

例如,如果写一条新消息,我希望它对用户只可见十个小时。使用 rest api & sql 数据库,我可以轻松地使用服务器时间(+十小时)创建结束日期时间并将消息保存在数据库中。为用户加载消息时,我可以选择结束日期时间在现在之前的所有消息。

如何使用 Firebase 实时数据库做到这一点?也许使用 Firebase 云功能?我不想使用客户端时间。

【问题讨论】:

    标签: android datetime firebase firebase-realtime-database google-cloud-functions


    【解决方案1】:

    这实际上是 Cloud Functions 的一个很好的使用示例。

    将消息保存到数据库时,您可以使用ServerValue.TIMESTAMP 自动插入 Firebase 服务器的时间戳,因此您可以执行以下操作:

    public void saveMessage(String content) {
        DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
    
        HashMap<String, Object> message = new HashMap<>();
        message.put("content", content);
        message.put("startTime", ServerValue.TIMESTAMP);
    
        messagesRef.push().setValue(message);
    }
    

    然后您可以将云函数附加到messages 位置以侦听新数据。此函数可以执行将 startTime 值添加 10 小时并将其保存为 endTime 回同一个孩子的逻辑,类似于:

    exports.calculateEndTime = functions.database
        .ref('/messages/{messageId}').onCreate(event => {
          const message = event.data.val();
    
          // Only calculate endTime if it doesn't already exist.
          if (message && !message.endTime) {
            // Add 10 hours (in milliseconds) to the startTime to obtain the endTime.
            const endTime = message.startTime + (10 * 3600000);
    
            // Update the Firebase Database with the new endTime value.
            return event.data.adminRef.update({
              endTime: endTime
            });
          }
        });
    

    最后,要查询消息列表以仅获取 endTime 尚未通过的消息,您可以执行以下操作:

    // Obtain the server time using the .info/serverTimeOffset value.
    DatabaseReference offsetRef = FirebaseDatabase.getInstance().getReference(".info/serverTimeOffset");
    offsetRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            // Calculate the estimated server time based on the offset.
            double offset = snapshot.getValue(Double.class);
            double estimatedServerTimeMs = System.currentTimeMillis() + offset;
    
            // Use this server time to get the messages.
            getMessages(estimatedServerTimeMs);
        }
    
        @Override
        public void onCancelled(DatabaseError error) { }
    });
    
    public void getMessages(double endTime) {
        DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
    
        // Create a query to limit results where endTime is greater than the current time.
        Query messagesQuery = messagesRef.orderByChild("endTime").startAt(endTime);
    
        messagesRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot message : dataSnapshot.getChildren()) {
                    // ...
                }
            }
    
            @Override
            public void onCancelled(FirebaseError firebaseError) { }
        });
    }
    

    此示例首先获取clock skew value (from .info/serverTimeOffset) 以计算估计的当前服务器时间,然后在startAt() 查询中使用它以仅在当前时间之后返回带有endTime 的消息。


    可能还有其他一些方法可以解决此问题,例如获取服务器时间戳并在保存消息的同时执行上述逻辑,或者甚至只是查询startTime(10 小时前使用startAt)。

    但是,使用 Cloud Functions 路由是确保在服务器端计算 endTime、快速保存新消息并且消息实际上在数据库中包含 endTime 值的好方法。

    【讨论】:

    • 从数据库读取消息时如何处理结束时间?如果只显示尚未结束的消息。
    • 我也为此添加了一个示例。
    猜你喜欢
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2020-03-27
    • 2020-08-04
    • 2017-09-20
    • 1970-01-01
    相关资源
    最近更新 更多