J'essaye d'analyser ça
2017-01-23T10: 12: 31.484Z
en utilisant natif ISO8601DateFormatter
classe fournie par iOS 10
mais échoue toujours. Si la chaîne ne contient pas de millisecondes, l'objet Date
est créé sans problème.
J'ai essayé ceci et beaucoup de combinaisons options
mais échoue toujours ...
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [.withInternetDateTime, .withDashSeparatorInDate, .withColonSeparatorInTime, .withColonSeparatorInTimeZone, .withFullTime]
Une idée? Merci!
Avant macOS 10.13/iOS 11 ISO8601DateFormatter
ne prend pas en charge les chaînes de date, y compris les millisecondes.
Une solution de contournement consiste à supprimer la partie en millisecondes avec une expression régulière.
let isoDateString = "2017-01-23T10:12:31.484Z"
let trimmedIsoString = isoDateString.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: trimmedIsoString)
Dans macOS 10.13+/iOS 11+, une nouvelle option est ajoutée pour prendre en charge les fractions de seconde:
static var withFractionalSeconds: ISO8601DateFormatter.Options { get }
let isoDateString = "2017-01-23T10:12:31.484Z"
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let date = formatter.date(from: isoDateString)
Pour les personnes qui ne sont pas encore prêtes à passer à iOS 11, vous pouvez toujours créer votre propre formateur pour gérer les millisecondes, par exemple:
extension DateFormatter {
static var iSO8601DateWithMillisec: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormatter
}
}
Usage:
let formater = DateFormatter.iSO8601DateWithMillisec
let date = formater.date(from: "2017-01-23T10:12:31.484Z")!
print(date) // output: 2017-01-23 10:12:31 +0000
Il est légèrement plus élégant que d'écrire une expression régulière pour éliminer les millisecondes de la chaîne d'entrée.
Peut-être que cela aidera à décoder des formats légèrement différents:
extension JSONDecoder {
enum DateDecodeError: String, Error {
case invalidDate
}
static var bestDateAttemptDecoder: JSONDecoder {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
if let dateSecs = try? container.decode(Double.self) {
return Date(timeIntervalSince1970: dateSecs)
}
if let dateSecs = try? container.decode(UInt.self) {
return Date(timeIntervalSince1970: TimeInterval(dateSecs))
}
let dateStr = try container.decode(String.self)
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
if let date = isoFormatter.date(from: dateStr) {
return date
}
isoFormatter.formatOptions = [.withInternetDateTime ]
if let date = isoFormatter.date(from: dateStr) {
return date
}
log.warning("Cannot decode date");
throw DateDecodeError.invalidDate
})
return decoder
}
}
De: https://Gist.github.com/th3m477/442a0d1da6354dd3b84e3b71df5dca6a