large - iOS Swift: obtenga la fecha y hora actuales.
obtener fecha actual swift 4 (5)
Estoy tratando de hacer una aplicación de asistencia y estoy realmente confundido acerca de la fecha y la hora en iOS y Firebase.
Uso la fecha como clave, esta es la estructura de mi base de datos Firebase.
--Employees
--Unique_ID
--Details
Name: John
--Attendance
--dateToday
Timein: 8:00 AM
Timeout: 5:00 PM
BreakStart: 12:00 PM
BreakFinish: 1:00 PM
Este es mi código para obtener la fecha y hora que usé como clave
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
}
Pero cuando lo convierto de nuevo, recibo el 2017-09-22 16:00:00 +0000, lo cual es incorrecto porque es el 23 de septiembre en mi ubicación.
¿Cuál es el código correcto para usar para que pueda obtener la fecha y hora correctas y la fecha y hora?
Cuando convierte una marca de tiempo UTC (es decir, 2017-11-06 20:15:33 -08: 00) en un objeto Date()
en Swift, Swift pone a cero la zona horaria a GMT (que es más o menos 0). Para calcular un intervalo de tiempo, esto no representa un problema porque, sin embargo, se agregan o restan de la puesta a cero muchas horas (y minutos, ya que hay varias zonas horarias que no están divididas en la hora, pero en: 45 o: 30) la zona horaria se agrega o se resta al valor de la hora de la fecha (y, a veces, de los minutos), por lo que el punto absoluto en el tiempo nunca cambia. Sin embargo, al convertir ese objeto de fecha en una cadena, utilizando DateFormatter()
o ISO8601DateFormatter()
, eso plantea un problema porque la zona horaria original se puso a cero.
Ahora, prefiero usar RFC3339 (es decir, 2017-11-06T20: 15: 33-08: 00), el formato compatible con Internet para el formato de hora estandarizado ISO8601. Lo más probable es que la API de terceros a la que se conectará algún día la usará, así que creo que todos deberíamos usarla ahora. El formato en Swift es yyyy-MM-dd''T''HH:mm:ssXXXXX
. Swift también tiene un ISO8601DateFormatter()
que puede convertir los literales de cadena en objetos de fecha de manera muy simple:
func getDateFromUTC(RFC3339: String) -> Date? {
let formatter = ISO8601DateFormatter()
return formatter.date(from: RFC3339)
}
Y el uso del formato RFC3339 también hace que extraer la zona horaria sea muy simple:
func getTimeZoneFromUTC(RFC3339: String) -> TimeZone? {
switch RFC3339.suffix(6) {
case "+05:45":
return TimeZone(identifier: "Asia/Kathmandu")
default:
return nil
}
}
Por supuesto, deberías completar las otras 37 zonas horarias utilizando los métodos que más te convengan. Y ahora, si desea formatear esa cadena literal en algo más fácil de usar, puede combinar los dos métodos anteriores en algo como esto:
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)
}
Y así, esta cadena "2018-11-06T17:00:00+05:45"
, que se expresa a las 5:00 PM en algún lugar de Katmandú, se imprimirá a las 5:00PM Tue, Nov 6 2018
, mostrando la hora local, independientemente de dónde esté la máquina es. Y, por supuesto, si no desea formatearlo usando su hora local contextual, simplemente no establezca la propiedad timeZone.
Como nota al margen de algunas de las sugerencias de este hilo, recomendaría almacenar fechas como cadenas en Firebase. El almacenamiento de fechas como cadenas, en particular utilizando un formato como RFC3339, hace que esta plataforma de datos sea agnóstica. Puede cambiar a cualquier base de datos en cualquier plataforma en cualquier marco y no tendría que cambiar ninguna lógica porque las cadenas siempre son solo cadenas. Y el RFC3339 es el único perfil que básicamente cualquier marco digno de su sal reconoce.
La forma sencilla de crear Current TimeStamp. como abajo,
func generateCurrentTimeStamp () -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy_MM_dd_hh_mm_ss"
return (formatter.string(from: Date()) as NSString) as String
}
Para guardar la hora actual en la base de datos de base de fuego, uso la conversación de Unic Epoch:
let timestamp = NSDate().timeIntervalSince1970
y para decodificar la fecha y hora de Unix hasta la fecha ().
let myTimeInterval = TimeInterval(timestamp)
let time = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))
Primero, le recomendaría que almacene su marca de tiempo como NSNumber
en su base de datos de Firebase, en lugar de almacenarla como una String
.
Otra cosa que vale la pena mencionar aquí es que si desea manipular las fechas con Swift, es mejor que use Date
lugar de NSDate
, excepto si está interactuando con algún código Obj-C en su aplicación.
Por supuesto, puede usar ambos, pero la Documentación dice:
Fecha de puentes a la clase NSDate. Puede usarlos indistintamente en el código que interactúa con las API de Objective-C.
Ahora, para responder a su pregunta, creo que el problema aquí se debe a la zona horaria.
Por ejemplo, si print(Date())
, como por ahora, obtendría:
2017-09-23 06:59:34 +0000
Este es el Tiempo Medio de Greenwich (GMT).
Entonces, dependiendo de dónde esté ubicado (o de dónde se encuentren sus usuarios), deberá ajustar la zona horaria antes (o después, cuando intente acceder a los datos, por ejemplo) almacenando su Date
:
let now = Date()
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let dateString = formatter.string(from: now)
Luego tiene su String
con String
formato String
, que refleja la hora actual en su ubicación, y tiene la libertad de hacer lo que quiera con ella :) ( NSNumber
a una Date
/ NSNumber
, o guárdela directamente como una String
en la base de datos. .)
Si solo desea la marca de tiempo de Unix, cree una extensión:
extension Date {
func currentTimeMillis() -> Int64 {
return Int64(self.timeIntervalSince1970 * 1000)
}
}
Entonces puedes usarlo como en otros lenguajes de programación:
let timestamp = Date().currentTimeMillis()