2015-03-24 15 views
15

Próbuję użyć sygnatur czasowych Firebase w aplikacji Swift. Chciałbym przechowywać je w mojej Bazie Firebase i używać ich jako rodzimych obiektów NSDate w mojej aplikacji.Próbujesz przekonwertować sygnaturę czasową Firebase na NSDate w Swift

Docs powiedzieć, że są UNIX czas epoka, więc próbowałem:

NSDate(timeIntervalSince1970:FirebaseServerValue.timestamp) 

bez powodzenia.

to:

FirebaseServerValue.timestamp 

powraca

0x00000001199298a0 

według debugera. Jaki jest najlepszy sposób przekazywania tych znaczników czasu?

Odpowiedz

28

ServerValue.timestamp() działa trochę inaczej niż ustawienie normalnych danych w Firebase. W rzeczywistości nie dostarcza znacznika czasu. Zamiast tego podaje wartość, która nakazuje serwerowi Firebase, aby wypełnił ten węzeł czasem. Korzystając z tego, znaczniki czasu Twojej aplikacji będą pochodzić z jednego źródła, Firebase, zamiast tego, co mówi urządzenie użytkownika.

Gdy otrzymasz wartość z powrotem (od obserwatora), otrzymasz czas jako milisekundę od epoki. Konieczne będzie przekonwertowanie go na sekundy, aby utworzyć NSDate. Oto fragment kodu:

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

Może się zdarzyć, że zostaną zebrane dwa zdarzenia z bardzo bliskimi znacznikami czasowymi. Dzieje się tak dlatego, że SDK najlepiej "zgaduje" w sygnaturze czasowej, zanim odezwie się z Firebase. Gdy usłyszy rzeczywistą wartość z Firebase, ponownie podniesie wartość.

+0

tutaj jest znacznik czasu ** "znacznik czasu": 1474536551180 ** a ten przekształca wartość ** 22.09.2016 9:29:11 + 0000 **. tutaj data jest OK, ale czas nie jest właściwy. Stworzyłem timestamp @ około 14.00 .. więc każdy pomysł na ten temat. zrobiłem to samo .. – Vats

+1

Konwertowany czas jest w UTC. W której strefie czasowej jesteś? – katfang

+0

Cześć, dziękuję za odpowiedź. Jestem z ** UTC + 05: 30 (Indie) ** – Vats

0

Dostaniesz właściwy czas jeśli używasz:

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

Można utworzyć nowy transformator na 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

4

To pytanie jest stary, ale niedawno miał ten sam problem, więc udzielę odpowiedzi.

Tutaj można zobaczyć jak ja zapisywania znacznika czasu do Firebase Database

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) 

Szczególnie istotne wiersz kodu "timestamp": [".sv": "timestamp"],

Oszczędza to znacznik czasu jako podwójne w swojej bazie danych. Jest to czas w milisekundach, więc musisz podzielić przez 1000, aby uzyskać czas w sekundach. Możesz zobaczyć przykładowy znacznik czasu na tym obrazku. Firebase Timestamp

Aby przekonwertować ten podwójny do Data napisałem następującą funkcję:

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

Daje to znacznik czasu, który wygląda tak: Timestamp

+0

Nie używasz 'ServerValue.timestamp()' bardziej niezawodne podejście? –

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

Przechowywać w Firebase coś jak [ktimeStamp:timestamp as AnyObject] niż po konwersji w kilka sekund przy użyciu serwera Firebase Server Time:

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

Oto kod, oparty na odpowiedzi alicanbatur, który pozwala, by data była podwójnym lub znacznikiem czasu serwera, a mimo to nadal działa w warstwie mapowania obiektów, takiej jak 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 
     } 
    } 
} 
Powiązane problemy