如何使用Firebase服务器时间戳生成日期?

时间:2016-06-16 16:45:45

标签: android firebase timestamp firebase-realtime-database

目前,Google的ServerValue.TIMESTAMP版本会返回{".sv":"timestamp"},用作Firebase的指令,以便在将数据保存到Firebase服务器后使用服务器时间戳填充该字段。

但是,当您在客户端创建数据时,您还没有实际的时间戳(即用作创建日期)。在初始保存和随后的检索之后,您只能访问时间戳,我想 - 有时候太晚了,不太优雅。

Google之前:

更新:忽略此部分,因为它不正确 - 我误解了这些示例。 ServerValue.TIMESTAMP始终返回{".sv":"timestamp"}

据我所知,在go-google Firebase中,似乎有一个服务器生成的时间戳可用于获取实际时间戳:

import com.firebase.client.ServerValue;
ServerValue.TIMESTAMP // eg. 1466094046

ref 1ref 2

问题:

  1. 这样的保存/检索是在我的模型实例上获取服务器生成的创建日期的唯一方法吗?
  2. 如果是,你可以提出一种实施这种模式的方法吗?
  3. 我是否正确理解ServerValue.TIMESTAMP已经因Google收购Firebase而发生变化? 更新:不,@ FrankkuPuffelen回复说在收购过程中没有任何改变。
  4. 注意:

    我不打算在客户端使用new Date(),因为我一直在阅读它并不安全,但如果您认为不同,请分享您的想法。

2 个答案:

答案 0 :(得分:25)

在写入操作中使用ServerValue.TIMESTAMP常量时,您表示Firebase数据库服务器在执行写入操作时应确定正确的时间戳。

我们说我们运行此代码:

ref.addValueEventListener(new ValueEventListener() {
    public void onDataChange(DataSnapshot dataSnapshot) {
        System.out.println(dataSnapshot.getValue()); 
    }

    public void onCancelled(DatabaseError databaseError) { }
});
ref.setValue(ServerValue.TIMESTAMP);

这将执行如下:

  1. 你附上一个听众
  2. 您使用ServerValue.TIMESTAMP
  3. 撰写了一个值
  4. Firebase客户端立即触发值事件,其中包含将在服务器上写入的时间戳的近似值
  5. 您的代码打印该值
  6. 写入操作将发送到Firebase服务器
  7. Firebase服务器确定实际时间戳并将值写入数据库(假设没有安全规则失败)
  8. Firebase服务器将实际时间戳发送回客户端
  9. Firebase客户端会为实际值
  10. 引发一个值事件
  11. 您的代码打印该值
  12. 如果您使用的是ChildEventListener而不是ValueEventListener,则客户将在步骤3中调用onChildAdded,在步骤8中调用onChildChanged

    自Firebase加入Google以来,我们生成ServerValue.TIMESTAMP的方式没有任何变化。之前有效的代码将继续有效。这也意味着first answer you linked是处理它的有效方式。

答案 1 :(得分:2)

我做的有点不同。

解决方案1:POJO中的push()方法

由于我不想用奇怪的吸气剂或属性来混淆我的POJO,我只是在我的POJO中定义一个push()方法,如下所示:

/**
 * Pushes a new instance to the DB.
 * 
 * @param parentNode `DatabaseReference` to the parent node this object shall be attached to
 */
fun push(parentNode: DatabaseReference) {
    parentNode
        .push()
        .apply {
            setValue(this@Pojo)
            child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP)
        }
}

然后我可以简单地创建一个POJO的实例并在其上调用push(),它正确地填充了创建时间属性。

这肯定会使POJO变得不那么简单,并且涉及POJO不应该知道的逻辑。但是,如某些响应here中所述,使用@Exclude注释和/或强制转换也需要了解存储机制。

解决方案2:助手或DatabaseReference分机(Kotlin)

为了解决这个问题,你当然也可以在帮助器中创建一个pushTask(task: Task)方法,或者 - 如果使用Kotlin - 一个扩展方法,例如DatabaseReference看起来像这样:

fun DatabaseReference.push(pojo: Pojo) {
    push()
    .apply {
        setValue(pojo)
        child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP)
    }
}

现在看着它,我开始认为我更喜欢第二种方法(如果我有Kotlin可供我使用 - 我不喜欢帮手)。但这可能只是一个品味问题。 ;)