如何在swift中解码firebase Firestore中的时间戳

如何在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”类型的值转换为预期的参数类

我想通过解析来自firestore数据库的响应来解码时间戳(由FirebaseFirestore.TimeStamp在swift中定义)

要从服务器解析的以下代码有编译器告诉我:

实例方法“decode(uquo:forKey:)”要求“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
  }