试图在Swift中将Firebase时间戳转换为NSDate

时间:2015-03-24 21:17:16

标签: ios swift firebase

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

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

NSDate(timeIntervalSince1970:FirebaseServerValue.timestamp)

没有运气。

此:

FirebaseServerValue.timestamp

返回

0x00000001199298a0

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

10 个答案:

答案 0 :(得分:35)

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

当您获得值(来自观察者)时,您将获得自纪元以来毫秒的时间。您需要将其转换为秒以创建NSDate。这是一段代码:

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事件。

答案 1 :(得分:6)

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

在这里,您可以看到我如何将时间戳保存到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"],

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

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

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)
    }

这会给出如下所示的时间戳:Timestamp

答案 2 :(得分:3)

如果你使用的话,你将得到合适的时间:

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)

答案 3 :(得分:1)

let serverTimeStamp = ServerValue.timestamp() as! [String:Any]

存储在Firebase之类的内容[ktimeStamp:timestamp as AnyObject] 而不是使用Firebase服务器时间在几秒钟内转换后:

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

答案 4 :(得分:1)

Firestore有一个API - &gt; - (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];

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

答案 5 :(得分:0)

您可以为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

答案 6 :(得分:0)

以下是基于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
        }
    }
}

答案 7 :(得分:0)

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

user.creationDate.dateValue()

答案 8 :(得分:0)

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
    }
})

答案 9 :(得分:0)

对我而言,迅速5在另一个课程中使用:

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