如何在swift中解码firebase Firestore中的时间戳
我想通过解析来自firestore数据库的响应来解码时间戳(由FirebaseFirestore.TimeStamp在swift中定义) 要从服务器解析的以下代码有编译器告诉我: 实例方法“decode(uquo:forKey:)”要求“Timestamp”符合 “可解码” 此外,我无法使用以下行进行编码(本地保存或发送到服务器):如何在swift中解码firebase Firestore中的时间戳,swift,firebase,timestamp,google-cloud-firestore,codable,Swift,Firebase,Timestamp,Google Cloud Firestore,Codable,我想通过解析来自firestore数据库的响应来解码时间戳(由FirebaseFirestore.TimeStamp在swift中定义) 要从服务器解析的以下代码有编译器告诉我: 实例方法“decode(uquo:forKey:)”要求“Timestamp”符合 “可解码” 此外,我无法使用以下行进行编码(本地保存或发送到服务器): try container.encode(created, forKey: .created) 编译器说: 无法将“Timestamp”类型的值转换为预期的参数类
try container.encode(created, forKey: .created)
编译器说:
无法将“Timestamp”类型的值转换为预期的参数类型
“字符串”
下面是完整的复制粘贴
此外,时间戳似乎是一个字典,而不是一个整数,因为当我尝试将时间戳解码为整数时,会出现以下错误:
Expected to decode Int but found a dictionary instead.
但我们都知道[String:Any](即字典)是不可能解码的
import FirebaseFirestore
class SomeClassToParseFromFirestoresDatabase: Codable
{
var created = FirebaseFirestore.Timestamp.init(date: Date())
private enum CodingKeys: String, CodingKey
{
case created
}
func encode(to encoder: Encoder) throws
{
var container = encoder.container(keyedBy: CodingKeys.self)
do
{
try container.encode(created, forKey: .created)
}
catch let error
{
print("error encoding to server or locally: \(error) ")
}
}
required init(from decoder: Decoder) throws
{
let container = try decoder.container(keyedBy: CodingKeys.self)
do
{
created = try container.decode(FirebaseFirestore.Timestamp.self, forKey: .created)
}
catch
{
print("error getting 'created' from server: \(error) ")
}
}
}
下面是如何解析来自https.callable firestore函数(只返回JSON)的响应的示例,以及如何使用自定义响应类解析响应中的时间戳(以及在类中存储时间戳)
有点不清楚问题中的代码在做什么,但如果我们简化这个过程,可能会有所帮助 这是一个将Firestore时间戳写入“Timestamp”集合的函数,每个文档都有一个唯一的documentID和一个子字段“stamp”
func writeTimestampAction() {
let now = Date()
let stamp = Timestamp(date: now)
let docRef = self.db.collection("timestamps").document()
docRef.setData( [
"stamp": stamp
])
}
然后是一个函数,用于读取该集合中的所有时间戳,并以yyyy-mm-dd格式将它们输出到控制台
func readTimestampAction() {
self.db.collection("timestamps").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
if let stamp = document.get("stamp") {
let title = document.documentID
let ts = stamp as! Timestamp
let aDate = ts.dateValue()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
let formattedTimeZoneStr = formatter.string(from: aDate)
print(title, formattedTimeZoneStr)
}
}
}
}
}
编辑
他是一个可以传递Firestore快照的活动类
class ActivityClass {
var activity_name = ""
var activity_date: Timestamp?
convenience init(withDoc: QueryDocumentSnapshot) {
self.init()
if let stamp = withDoc.get("stamp") {
self.activity_date = stamp as? Timestamp
}
}
}
当您从Firestore检索数据时,只需执行以下操作
for document in querySnapshot!.documents {
let myActivity = ActivityClass(withDoc: document)
//do something with myActivity
我需要做两件事 第一件事是使用timeStamp的“toString()”在服务器端“设置”我的日期-尽管默认情况下它看起来像字符串,但timeStamp不是字符串,客户端解析空字典 然后,我可以将该字符串转换为具有以下日期格式的日期
let d = try container.decode(String.self, forKey: .created)
//example: Fri Apr 26 2019 17:25:22
let index = d.index(d.endIndex, offsetBy: -15)
let abc = d[..<index]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss"
if let d = dateFormatter.date(from:String(abc))
{
created = d
}
let d=try container.decode(String.self,forKey:.created)
//示例:2019年4月26日星期五17:25:22
let index=d.index(d.endIndex,偏移量:-15)
让abc=d[…谢谢。我想做相反的事情(从https可调用响应将firestore时间戳读入本地类)-我更新了我的post@aman与什么相反?这个答案演示了如何既写时间戳又读时间戳?如果时间戳存在,只需使用答案的第二部分,一旦你用读取时间戳,让ts=stamp as!timestamp
,将它存储在你的类中。对不起,我现在明白了。我想我不明白怎么做翻译您所写的内容-将文档解析为Swift的本地编码Protocol@aman我想我的问题是,你为什么要使用可编码协议?为什么不将Firestore返回的快照传递给类?这可能会使代码更易于阅读,更易于扩展和维护。我更新了我的答案,并提出了一个建议。Maybe这不是你想去的方向,但它很干净。谢谢Jay。响应来自云中的一个可调用函数(不是使用firebase“db”的本地客户端SDK)-所以我需要解析来自NSData的响应。另外,我正在使用协议,因为我有一个保持所有响应同质的数据模型。这只是意味着-所有响应都有“success”(true或false)“message”(如果success==false,则显示错误消息),然后是一些可以是任意键的数据。同样,对于每个响应,我都将数据保存在本地,然后将数据解包到UI中。
for document in querySnapshot!.documents {
let myActivity = ActivityClass(withDoc: document)
//do something with myActivity
let d = try container.decode(String.self, forKey: .created)
//example: Fri Apr 26 2019 17:25:22
let index = d.index(d.endIndex, offsetBy: -15)
let abc = d[..<index]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss"
if let d = dateFormatter.date(from:String(abc))
{
created = d
}