ios 尝试在 Swift 中将 Firebase 时间戳转换为 NSDate
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29243060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Trying to convert Firebase timestamp to NSDate in Swift
提问by Fook
I'm trying to use Firebase timestamps in a Swift app. I'd like to store them in my Firebase, and use them as native NSDate objects in my app.
我正在尝试在 Swift 应用中使用 Firebase 时间戳。我想将它们存储在我的 Firebase 中,并在我的应用程序中将它们用作本机 NSDate 对象。
The docs say they are unix epoch time, so I've tried:
文档说他们是unix时代,所以我试过:
NSDate(timeIntervalSince1970:FirebaseServerValue.timestamp)
with no luck.
没有运气。
This:
这个:
FirebaseServerValue.timestamp
returns
返回
0x00000001199298a0
according to the debugger. What is the best way to pass these timestamps around?
根据调试器。传递这些时间戳的最佳方法是什么?
回答by katfang
ServerValue.timestamp()
works a little differently than setting normal data in Firebase. It does not actually provide a timestamp. Instead, it provides a value which tells the Firebase server to fill in that node with the time. By using this, your app's timestamps will all come from one source, Firebase, instead of whatever the user's device happens to say.
ServerValue.timestamp()
与在 Firebase 中设置普通数据的工作方式略有不同。它实际上并不提供时间戳。相反,它提供了一个值,告诉 Firebase 服务器用时间填充该节点。通过使用它,您的应用的时间戳将全部来自一个来源 Firebase,而不是用户的设备所说的任何内容。
When you get the value back (from a observer), you'll get the time as milliseconds since the epoch. You'll need to convert it to seconds to create an NSDate. Here's a snippet of code:
当您(从观察者)取回值时,您将获得自纪元以来的毫秒数。您需要将其转换为秒以创建 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))
}
})
You may find that you get two events raised with very close timestamps. This is because the SDK will take a best "guess" at the timestamp before it hears back from Firebase. Once it hears the actual value from Firebase, it will raise the Value event again.
您可能会发现,您会收到两个时间戳非常接近的事件。这是因为 SDK 在收到 Firebase 的回复之前会在时间戳上进行最佳“猜测”。一旦它从 Firebase 听到实际值,它就会再次引发 Value 事件。
回答by DoesData
This question is old, but I recently had the same problem so I'll provide an answer.
这个问题很老了,但我最近遇到了同样的问题,所以我会提供一个答案。
Here you can see how I am saving a timestamp to Firebase Database
在这里您可以看到我如何将时间戳保存到 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)
The particularly relevant line of code is "timestamp": [".sv": "timestamp"],
特别相关的代码行是 "timestamp": [".sv": "timestamp"],
This saves the timestamp as a double in your database. This is the time in milliseconds so you need to divide by 1000 in order to get the time in seconds. You can see a sample timestamp in this image.
这会将时间戳保存为数据库中的双精度值。这是以毫秒为单位的时间,因此您需要除以 1000 才能获得以秒为单位的时间。您可以在此图像中看到示例时间戳。
To convert this double into a Date I wrote the following function:
为了将此双精度转换为日期,我编写了以下函数:
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)
}
回答by Raul Quispe
For me in swift 5 use in another class:
对于我在 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()
}
回答by TAREK
You will get the right time if you use:
如果您使用,您将获得正确的时间:
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)
回答by Nikhil Jobanputra
let serverTimeStamp = ServerValue.timestamp() as! [String:Any]
Store in Firebase
something like [ktimeStamp:timestamp as AnyObject]
than after you convert in seconds using Firebase Server Time:
使用 Firebase 服务器时间在几秒钟内转换后存储在Firebase
类似的内容中[ktimeStamp:timestamp as AnyObject]
:
let timestampDate = NSDate(timeIntervalSince1970: Double(timestamp as! NSNumber)/1000)
回答by Mike Critchley
Firestore has an API for this --> -(NSDate *)dateValue
Firestore 对此有一个 API --> -(NSDate *)dateValue
For example, if you have saved(set) a new document with a field "createdAtDate"
例如,如果您已保存(设置)一个带有“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) {
}
You can get back this information either with a get query or via setting a listener. When you have the snapshot back, just access the dates you saved and convert to NSDate.
您可以通过获取查询或通过设置侦听器来获取此信息。当您恢复快照时,只需访问您保存的日期并转换为 NSDate。
NSDate *date1 = [snapshot.data[@"createdAtDate"] dateValue];
NSDate *date2 = [snapshot.data[@"lastModifiedDate"] dateValue];
There will be a slight loss in precision, but as most people use dates for data synchronization or sorts, I can't think of a case where the loss of precision would be an issue.
精度会略有下降,但由于大多数人使用日期进行数据同步或排序,我想不出精度损失会成为问题的情况。
回答by Noodybrank
You can get a date approximation from Firebase. For example if you're trying to change a firebase user's creation date (a Timestamp) to a Date:
您可以从 Firebase 获得近似日期。例如,如果您尝试将 firebase 用户的创建日期(时间戳)更改为日期:
user.creationDate.dateValue()
回答by Aaron Halvorsen
Swift 4 and updated Firebase library variation of Katfang's answer:
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
}
})
回答by phatmann
Here is some code, based on alicanbatur's answer, that allows a date to be a Double or a server timestamp, and yet still work within an object mapping layer such as ObjectMapper.
这是一些基于 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
}
}
}
回答by alicanbatur
You can create a new transformer for ObjectMapper,
您可以为 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
}
}