web-dev-qa-db-ger.com

iOS Swift - Ruft die aktuelle Ortszeit und den Datumszeitstempel ab

Ich versuche eine Anwesenheits-App zu erstellen und bin in Bezug auf Datum und Uhrzeit in iOS und Firebase wirklich verwirrt.

Ich verwende Datum als Schlüssel, dies ist die Struktur meiner Firebase-Datenbank.

--Employees
  --Unique_ID
     --Details
          Name: John
     --Attendance
          --dateToday
              Timein: 8:00 AM
              Timeout: 5:00 PM
              BreakStart: 12:00 PM
              BreakFinish: 1:00 PM

Dies ist mein Code, um den Datumszeitstempel zu erhalten, den ich als Schlüssel verwendet habe

 override func viewDidLoad() {
     super.viewDidLoad()

     let now = NSDate()
     let nowTimeStamp = self.getCurrentTimeStampWOMiliseconds(dateToConvert: now)

     // I save this dateToday as Key in Firebase
     dateToday = nowTimeStamp
}


func getCurrentTimeStampWOMiliseconds(dateToConvert: NSDate) -> String {
    let objDateformat: DateFormatter = DateFormatter()
    objDateformat.dateFormat = "yyyy-MM-dd"
    let strTime: String = objDateformat.string(from: dateToConvert as Date)
    let objUTCDate: NSDate = objDateformat.date(from: strTime)! as NSDate
    let milliseconds: Int64 = Int64(objUTCDate.timeIntervalSince1970)
    let strTimeStamp: String = "\(milliseconds)"
    return strTimeStamp
}

Aber wenn ich es zurück konvertiere, bekomme ich 2017-09-22 16:00:00 +0000.

Was ist der richtige Code, um den korrekten Datums- und Zeitstempel zu erhalten? 

17
TSM

Um die aktuelle Zeit für die Firebase-Datenbank zu speichern, verwende ich Unic Epoch Conversation:

let timestamp = NSDate().timeIntervalSince1970

und zum Entschlüsseln der Unix-Epoche bis zum Datum ().

let myTimeInterval = TimeInterval(timestamp)
let time = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))
38
Satish Babariya

Zuerst würde ich Ihnen empfehlen, Ihren Zeitstempel als NSNumber in Ihrer Firebase-Datenbank zu speichern, anstatt ihn als String zu speichern.

Eine weitere erwähnenswerte Sache ist, dass Sie, wenn Sie Daten mit Swift bearbeiten möchten, Date anstelle von NSDate verwenden sollten, es sei denn, Sie interagieren mit Obj-C-Code in Ihrer App .

Sie können natürlich beide verwenden, aber in der Dokumentation heißt es:

Datumsbrücken zur NSDate-Klasse. Sie können diese austauschbar in .__ verwenden. Code, der mit Objective-C-APIs interagiert.

Nun, um Ihre Frage zu beantworten, denke ich, liegt das Problem an der Zeitzone. 

Wenn Sie zum Beispiel print(Date()) für jetzt haben, würden Sie Folgendes erhalten:

2017-09-23 06:59:34 +0000

Dies ist die Greenwich Mean Time (GMT).

Abhängig davon, wo Sie sich befinden (oder wo sich Ihre Benutzer befinden), müssen Sie die Zeitzone vor (oder nach, wenn Sie beispielsweise versuchen, auf die Daten zuzugreifen) anpassen, indem Sie Date speichern:

    let now = Date()

    let formatter = DateFormatter()

    formatter.timeZone = TimeZone.current

    formatter.dateFormat = "yyyy-MM-dd HH:mm"

    let dateString = formatter.string(from: now)

Dann haben Sie Ihre richtig formatierte Variable String, die die aktuelle Uhrzeit an Ihrem Standort widerspiegelt, und Sie können alles tun, was Sie möchten. :) (Konvertieren Sie sie in eine Variable Date/NSNumber oder speichern Sie es direkt als String in der Datenbank ..)

8
Alex

Wenn Sie nur den Unix-Zeitstempel haben möchten, erstellen Sie eine Erweiterung:

extension Date {
    func currentTimeMillis() -> Int64! {
        return Int64(self.timeIntervalSince1970 * 1000)
    }
}

Dann können Sie es wie in anderen Programmiersprachen verwenden:

let timestamp = Date().currentTimeMillis()
3
lenooh

Die einfache Methode zum Erstellen von Current TimeStamp. Wie unten,

func generateCurrentTimeStamp () -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy_MM_dd_hh_mm_ss"
    return (formatter.string(from: Date()) as NSString) as String
}
2
User558

Wenn Sie einen UTC-Zeitstempel (d. H. 2017-11-06 20:15:33 -08: 00) in ein Date()-Objekt in Swift konvertieren, setzt Swift die Zeitzone auf GMT (was plus oder minus 0 ist) aus. Für die Berechnung eines Zeitintervalls stellt dies kein Problem dar, da jedoch viele Stunden (und Minuten, da es eine Anzahl von Zeitzonen gibt, die nicht auf die Stunde, sondern auf: 45 oder: 30) aufgeteilt sind, oder vom Nullabgleich abgezogen werden außerhalb der Zeitzone werden die Stunden (und manchmal Minuten) des Datums addiert oder davon abgezogen, so dass sich der absolute Zeitpunkt niemals ändert. Wenn Sie dieses Datumsobjekt mithilfe von DateFormatter() oder ISO8601DateFormatter() in einen String konvertieren, stellt dies jedoch ein Problem dar, da die ursprüngliche Zeitzone auf Null gesetzt wurde.

Ich bevorzuge die Verwendung von RFC3339 (d. H. 2017-11-06T20: 15: 33-08: 00), das internetfreundliche Format für das nach ISO 8601 standardisierte Zeitformat. Die Chancen der Drittanbieter-API, an die Sie sich eines Tages anschließen werden, werden wahrscheinlich davon Gebrauch machen. Ich denke, wir sollten es jetzt alle verwenden. Das Format in Swift ist yyyy-MM-dd'T'HH:mm:ssXXXXX. Swift hat auch eine ISO8601DateFormatter(), die sehr einfach String-Literale in Datumsobjekte umwandeln kann:

func getDateFromUTC(RFC3339: String) -> Date? {
    let formatter = ISO8601DateFormatter()
    return formatter.date(from: RFC3339)
}

Die Verwendung des RFC3339-Formats macht das Extrahieren der Zeitzone ebenfalls sehr einfach:

func getTimeZoneFromUTC(RFC3339: String) -> TimeZone? {
    switch RFC3339.suffix(6) {
    case "+05:45":
        return TimeZone(identifier: "Asia/Kathmandu")
    default:
        return nil
    }
}

Natürlich müssen Sie die anderen 37 Zeitzonen mit den für Sie geeigneten Methoden ausfüllen. Wenn Sie nun das Zeichenkettenliteral benutzerfreundlicher formatieren möchten, können Sie die beiden oben genannten Methoden in etwa wie folgt kombinieren:

func getFormattedDateFromUTC(RFC3339: String) -> String? {
    guard let date = getDateFromUTC(RFC3339: RFC3339),
        let timeZone = getTimeZoneFromUTC(RFC3339: RFC3339) else {
            return nil
    }
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mma EEE, MMM d yyyy"
    formatter.amSymbol = "AM"
    formatter.pmSymbol = "PM"
    formatter.timeZone = timeZone // preserve local time zone
    return formatter.string(from: date)
}

Und diese Zeichenfolge "2018-11-06T17:00:00+05:45", die irgendwo in Kathmandu um 17:00 Uhr ausgedrückt wird, gibt 5:00PM Tue, Nov 6 2018 aus, wobei die Ortszeit angezeigt wird, unabhängig davon, wo sich die Maschine befindet. Wenn Sie es nicht mit der lokalen Ortszeit formatieren möchten, setzen Sie die timeZone-Eigenschaft natürlich nicht.

Als Randbemerkung zu einigen der Vorschläge in diesem Thread würde ich empfehlen, Datumsangaben als Zeichenfolgen in Firebase zu speichern. Durch das Speichern von Datumsangaben als Zeichenfolgen, insbesondere unter Verwendung eines Formats wie RFC3339, wird diese Datenplattform agnostisch. Sie können zu jeder Datenbank auf jeder Plattform in einem beliebigen Framework wechseln, und Sie müssen keine Logik ändern, da Strings immer nur Strings sind. Und RFC3339 ist das einzige Profil, das grundsätzlich jedes Gerüst erkennt, das es wert ist, Salz zu gewinnen.

0
bsod