如何在Firebase实时数据库中使用结束日期时间

iqp*_*lar 2 datetime android firebase firebase-realtime-database google-cloud-functions

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

例如,如果要编写新邮件,我希望用户只能看到它10个小时.使用rest api和sql数据库,我可以轻松地创建服务器时间(+十小时)的结束日期时间并将消息保存在数据库中.为用户加载消息时,我可以选择结束日期时间之前的所有消息.

如何使用Firebase实时数据库执行此操作?也许使用Firebase云功能?我不想使用客户端时间.

Gri*_*orr 5

这实际上是云功能的一个很好的用法示例.

将邮件保存到数据库时,您可以使用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);
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将云功能附加到该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
        });
      }
    });
Run Code Online (Sandbox Code Playgroud)

最后,要查询消息列表以仅获取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) { }
    });
}
Run Code Online (Sandbox Code Playgroud)

此示例首先获取时钟偏差值(from .info/serverTimeOffset)以计算估计的当前服务器时间,然后在startAt()查询中使用此值仅返回endTime当前时间之后的消息.


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

但是,使用云功能路由是确保endTime计算服务器端的一种好方法,可以快速执行新消息的保存,并且消息实际上包含endTime数据库中的值.