【问题标题】:Trying to convert Firebase timestamp to NSDate in Swift尝试在 Swift 中将 Firebase 时间戳转换为 NSDate
【发布时间】:2015-05-28 09:06:54
【问题描述】:

我正在尝试在 Swift 应用中使用 Firebase 时间戳。我想将它们存储在我的 Firebase 中,并在我的应用中将它们用作本机 NSDate 对象。

文档说它们是 unix 纪元时间,所以我试过了:

NSDate(timeIntervalSince1970:FirebaseServerValue.timestamp)

没有运气。

这个:

FirebaseServerValue.timestamp

返回

0x00000001199298a0

根据调试器。传递这些时间戳的最佳方式是什么?

【问题讨论】:

    标签: ios swift firebase


    【解决方案1】:

    ServerValue.timestamp() 的工作方式与在 Firebase 中设置普通数据略有不同。它实际上并不提供时间戳。相反,它提供了一个值,告诉 Firebase 服务器用时间填充该节点。通过使用它,您的应用的时间戳将全部来自一个来源,即 Firebase,而不是用户设备碰巧说的任何内容。

    当您(从观察者)取回该值时,您将获得自纪元以来的毫秒数。您需要将其转换为秒才能创建 NSDate。这是一段sn-p代码:

    let ref = Firebase(url: "<FIREBASE HERE>")
    
    // Tell the server to set the current timestamp at this location.
    ref.setValue(ServerValue.timestamp()) 
    
    // Read the value at the given location. It will now have the time.
    ref.observeEventType(.Value, withBlock: { 
        snap in
        if let t = snap.value as? NSTimeInterval {
            // Cast the value to an NSTimeInterval
            // and divide by 1000 to get seconds.
            println(NSDate(timeIntervalSince1970: t/1000))
        }
    })
    

    您可能会发现引发了两个时间戳非常接近的事件。这是因为 SDK 会在收到 Firebase 的回复之前对时间戳进行最佳“猜测”。一旦它从 Firebase 听到实际值,它将再次引发 Value 事件。

    【讨论】:

    • 这里是时间戳 "timestamp": 1474536551180 这是转换后的值 2016-09-22 09:29:11 +0000 。这里日期可以,但时间不合适。我已经在下午 2 点左右创建了时间戳 @ .. 所以对此有任何想法。我也是这样做的。。
    • 转换后的时间为 UTC。你在哪个时区?
    • 您好,感谢您的回复。我来自 UTC+05:30(印度)
    • 时间戳是 Firebase 的服务器时间,而不是单个设备的时间。
    • @katfang 你能在objective-c中提供上面的代码吗?
    【解决方案2】:

    对于我在 swift 5 中使用另一个类:

    import FirebaseFirestore
    init?(document: QueryDocumentSnapshot) {
            let data = document.data()
           guard let stamp = data["timeStamp"] as? Timestamp else {
                return nil
            }
           let date = stamp.dateValue()
    }
    

    【讨论】:

    • 这应该是今天公认的答案。将数据设置为存储在 Firebase 中时,请使用 Date。检索时,使用此答案将时间戳转换为日期。
    【解决方案3】:

    这个问题很老了,但我最近遇到了同样的问题,所以我会提供一个答案。

    在这里您可以看到我如何将时间戳保存到 Firebase 数据库

     let feed = ["userID": uid,
                 "pathToImage": url.absoluteString,
                 "likes": 0,
                 "author": Auth.auth().currentUser!.displayName!,
                 "postDescription": self.postText.text ?? "No Description",
                 "timestamp": [".sv": "timestamp"],
                 "postID": key] as [String: Any]
    
     let postFeed = ["\(key)" : feed]
    
     ref.child("posts").updateChildValues(postFeed)
    

    特别相关的代码行是"timestamp": [".sv": "timestamp"],

    这会将时间戳作为双精度保存在您的数据库中。这是以毫秒为单位的时间,因此您需要除以 1000 才能获得以秒为单位的时间。您可以在此图像中看到示例时间戳。

    为了将这个双精度转换为日期,我编写了以下函数:

    func convertTimestamp(serverTimestamp: Double) -> String {
            let x = serverTimestamp / 1000
            let date = NSDate(timeIntervalSince1970: x)
            let formatter = DateFormatter()
            formatter.dateStyle = .long
            formatter.timeStyle = .medium
    
            return formatter.string(from: date as Date)
        }
    

    这给出了一个看起来像这样的时间戳:

    【讨论】:

    • 使用ServerValue.timestamp() 不是更稳健的方法吗?
    【解决方案4】:

    如果你使用,你会得到正确的时间:

    let timestamp = FIRServerValue.timestamp()
    
    let converted = NSDate(timeIntervalSince1970: timestamp / 1000)
    
    
    let dateFormatter = NSDateFormatter()
    dateFormatter.timeZone = NSTimeZone.localTimeZone()
    dateFormatter.dateFormat = "hh:mm a"
    let time = dateFormatter.stringFromDate(converted)
    

    【讨论】:

      【解决方案5】:
      let serverTimeStamp = ServerValue.timestamp() as! [String:Any]
      

      存储在Firebase 类似[ktimeStamp:timestamp as AnyObject] 比使用 Firebase 服务器时间在几秒钟内转换之后:

      let timestampDate = NSDate(timeIntervalSince1970: Double(timestamp as! NSNumber)/1000)
      

      【讨论】:

        【解决方案6】:

        Firestore 对此有一个 API --> -(NSDate *)dateValue

        例如,如果您保存(设置)了一个带有“createdAtDate”字段的新文档

            NSDictionary *dataToBeSaved = @{
                //Tell the server to save FIRTimestamps when the document is created
                @"createdAtDate":[FIRFieldValue fieldValueForServerTimestamp],
                @"lastModifiedDate":[FIRFieldValue fieldValueForServerTimestamp],
        
               //Other fields
               @"userName":@"Joe Blow"
            }
        
            [myFirReference setData:[dataToBeSaved]
                            options:[FIRSetOptions merge]
                         completion:^(NSError* error) {
          }
        

        您可以通过 get 查询或设置侦听器来取回此信息。当您恢复快照后,只需访问您保存的日期并转换为 NSDate。

          NSDate *date1 = [snapshot.data[@"createdAtDate"] dateValue];
          NSDate *date2 = [snapshot.data[@"lastModifiedDate"] dateValue];
        

        精度会略有损失,但由于大多数人使用日期进行数据同步或排序,我想不出精度损失会成为问题的情况。

        【讨论】:

          【解决方案7】:

          您可以为 ObjectMapper 创建一个新的转换器,

          import Foundation
          import ObjectMapper
          
          class FirebaseDateTransform: TransformType {
              public typealias Object = Date
              public typealias JSON = Double
          
              open func transformFromJSON(_ value: Any?) -> Date? {
                  if let millisecondsSince1970 = value as? Double {
                      return Date(timeIntervalSince1970: millisecondsSince1970 / 1000.0)
                  }
          
                  return nil
              }
          
              open func transformToJSON(_ value: Date?) -> Double? {
                  if let date = value {
                      return Double(date.timeIntervalSince1970) * 1000.0
                  }
          
                  return nil
              }
          }
          

          Gist

          【讨论】:

            【解决方案8】:

            这里有一些代码,基于 alicanbatur 的回答,它允许日期为 Double 或服务器时间戳,但仍可在 ObjectMapper 等对象映射层中工作。

            enum FirebaseDate {
                case date(Date)
                case serverTimestamp
            
                var date: Date {
                    switch self {
                    case .date(let date):
                        return date
                    case .serverTimestamp:
                        return Date()
                    }
                }
            }
            
            class FirebaseDateTransform: TransformType {
                public typealias Object = FirebaseDate
                public typealias JSON = Any
            
                open func transformFromJSON(_ value: Any?) -> FirebaseDate? {
                    switch value {
                    case let millisecondsSince1970 as Double:
                        let date = Date(millisecondsSince1970: millisecondsSince1970)
                        return .date(date)
                    case is [AnyHashable: Any]?:
                        return .serverTimestamp
                    default:
                        return nil
                    }
                }
            
                open func transformToJSON(_ value: FirebaseDate?) -> Any? {
                    switch value {
                    case .date(let date)?:
                        return date.millisecondsSince1970
                    case .serverTimestamp?:
                        return ServerValue.timestamp()
                    default:
                        return nil
                    }
                }
            }
            

            【讨论】:

              【解决方案9】:

              您可以从 Firebase 获得一个日期近似值。例如,如果您尝试将 firebase 用户的创建日期(时间戳)更改为日期:

              user.creationDate.dateValue()
              

              【讨论】:

                【解决方案10】:

                Swift 4 和 Katfang 答案的更新 Firebase 库变体:

                let currentTimeStamp: TimeInterval?
                
                let ref = Database.database().reference().child("serverTimestamp")
                
                ref.setValue(ServerValue.timestamp())
                
                ref.observe(.value, with: { snap in
                    if let t = snap.value as? TimeInterval {
                    print(t/1000)
                    currentTimeStamp = t/1000
                    }
                })
                

                【讨论】:

                  猜你喜欢
                  • 2012-03-19
                  • 2011-09-18
                  • 2018-12-09
                  • 2015-01-06
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多