如何使用Firebase服务器时间戳生成date?
目前,Google版本的ServerValue.TIMESTAMP
返回{".sv":"timestamp"}
,一旦您将数据保存到Firebase服务器,该版本将作为Firebase的指令使用服务器时间戳填充该字段。
但是,当您在客户端创build数据时,您还没有实际的时间戳(即用作创builddate)。 在初始保存和随后的检索之后,您只能访问时间戳,我想 – 这有时为时已晚,不够优雅。
Google之前:
更新:忽略这一部分,因为它是不正确的 – 我误解了这些例子。 ServerValue.TIMESTAMP
总是返回{".sv":"timestamp"}
。
据我所知,在谷歌Firebase之前,似乎有一个服务器生成的时间戳,允许您获取实际的时间戳:
import com.firebase.client.ServerValue; ServerValue.TIMESTAMP // eg. 1466094046
( 参考文献1 , 参考文献2 )
问题:
- 这样的保存/检索是获得我的模型实例上的服务器生成的创builddate的唯一方法吗?
- 如果是的话,你能提出一个实施这种模式的方法吗?
- 我是否正确理解ServerValue.TIMESTAMP随着Google收购Firebase而改变? 更新:不,@FrankvanPuffelen回复说,收购过程中没有任何变化。
注意:
我不考虑在客户端使用new Date()
,因为我一直在阅读它是不安全的,但如果你认为不同,请分享你的想法。
在写入操作中使用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);
这将执行如下:
- 你附加一个监听器
- 你用
ServerValue.TIMESTAMP
写一个值 - Firebase客户端会立即触发一个值事件,并将其大致写入服务器的时间戳
- 你的代码打印这个值
- 写入操作被发送到Firebase服务器
- Firebase服务器确定实际的时间戳并将值写入数据库(假设没有安全规则失败)
- Firebase服务器会将实际的时间戳发送回客户端
- Firebase客户端会为实际价值提出价值事件
- 你的代码打印这个值
如果您使用ValueEventListener
而不是ValueEventListener
,则客户端将在步骤3中调用onChildAdded
,并在步骤8中调用onChildAdded
。
自从FirebasejoinGoogle后,我们生成ServerValue.TIMESTAMP
的方式没有任何变化。 以前工作的代码将继续工作。 这也意味着你链接的第一个答案是一个有效的方法来处理它。
我做的有点不同
解决scheme1:POJO中的push()
方法
因为我不想用奇怪的getter或属性来混淆我的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) } }
然后,我可以简单地创build一个POJO的实例,并调用push()
来正确地填充创build时间属性。
这绝对使得POJO不那么简单,并且涉及POJO不应该知道的逻辑。 然而,使用@Exclude
注释和/或强制转换在这里的一些响应中概述也需要知道存储机制。
解决scheme2:Helper或DatabaseReference
扩展(Kotlin)
为了克服这个问题,你当然也可以在助手中创build一个pushTask(task: Task)
方法,或者 – 如果使用Kotlin – 一个扩展方法,例如DatabaseReference
,它看起来像这样:
fun DatabaseReference.push(pojo: Pojo) { push() .apply { setValue(pojo) child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP) } }
现在看,我觉得我其实更喜欢第二种方法( 如果我有Kotlin在我手中 – 我不喜欢帮手)。 但这可能只是一个口味问题。 ;)