DateDecodingStrategy del tiempo de análisis de JSONDecoder

Cuando usamos los datos JSON devueltos por la API serial JSONDecoder, generalmente asignamos los datos en el campo de tiempo al tipo de Fecha, para que la aplicación pueda usar algunas funciones de cálculo de tiempo más adelante. Sin embargo, la hora devuelta por la API tiene muchos formatos, por lo que debemos indicarle al JSONDecoder el formato de la hora para que pueda analizar la hora y almacenarla como tipo Fecha.

Las tres API anteriores, respectivamente, devuelven diferentes formatos de tiempo

DateDecodingStrategy del tiempo de análisis de JSONDecoder

Podemos establecer el formato de hora de JSON a través de dateDecodingStrategy de JSONDecoder.

El tipo de dateDecodingStrategy es DateDecodingStrategy. Podemos establecer los siguientes formatos. A continuación, vamos a presentar varios formatos de hora comunes con ejemplos prácticos.

enum DateDecodingStrategy {
case deferredToDate
case secondsSince1970
case millisecondsSince1970
case iso8601
case formatted(DateFormatter)
case custom((Decoder) throws -> Date)
}

Ejemplo: API de iTunes.

https://itunes.apple.com/search?term=beatles&media=music

struct ItunesResult: Decodable {
    let results: [Song]
}
struct Song: Decodable {
    let trackName: String
    let releaseDate: Date
}
if let url = URL(string: "https://itunes.apple.com/search?term=beatles&media=music") {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        if let data = data, let itunesResult = try? decoder.decode(ItunesResult.self, from: data) {
            print(itunesResult.results.first)
        }
    }.resume()
}

segundosDesde 1970

Ejemplo: IG API.

https://www.instagram.com/lepetitprinceofficiel/?__a=1

Cuando el tiempo devuelto en segundo plano es una cadena de números, existe una alta probabilidad de que sea el número de segundos que faltan desde 1970.1.1. También podemos generar la Fecha en el campo de juegos de Xcode primero, y pasar el parámetro timeIntervalSince1970 al backend para probar si la Fecha generada es razonable.

struct IGResult: Decodable {
    let graphql: Graphql
}
struct Graphql: Decodable {
    let user: User
}
struct User: Decodable {
    let edgeOwnerToTimelineMedia: TimelineMedia
}
struct TimelineMedia: Decodable {
    let edges: [Edge]
}
struct Edge: Decodable {
    let node: Node
}
struct Node: Decodable {
    let takenAtTimestamp: Date
}
if let url = URL(string: "https://www.instagram.com/lepetitprinceofficiel/?__a=1") {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .secondsSince1970
        if let data = data, let igResult = try? decoder.decode(IGResult.self, from: data) {
            print(igResult.graphql.user.edgeOwnerToTimelineMedia.edges.first?.node.takenAtTimestamp)
        }
    }.resume()
}

milisegundos Desde 1970

Ejemplo: API covid19uk.

https://api.covid19uk.live/historyfigures

Como se mencionó anteriormente, cuando el tiempo devuelto en segundo plano es una serie de números, existe una alta probabilidad de que sea el número de segundos de 1970.1.1, pero también puede ser el número de milisegundos de 1970.1.1. Por lo tanto, si usa secondsSince1970 para obtener una gran cantidad de tiempo anormal, recuerde intentar milisegundosSince1970 nuevamente.

struct CovidData: Decodable {
    let data: [Record]
}
struct Record: Decodable {
    let date: Date
}
if let url = URL(string: "https://api.covid19uk.live/historyfigures") {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .millisecondsSince1970
        if let data = data, let covidData = try? decoder.decode(CovidData.self, from: data) {
            print(covidData.data.first?.date)
        }
    }.resume()
}

formateado

Ejemplo: API de máscara.

https://quality.data.gov.tw/dq_download_json.php?nid=116285&md5_url=2150b333756e64325bdbc4a5fd45fad1

struct Mask: Decodable {
    let name: String
    let time: Date
    
    enum CodingKeys: String, CodingKey  {
        case name = "醫事機構名稱"
        case time = "來源資料時間"
    }
}
if let url = URL(string: "https://quality.data.gov.tw/dq_download_json.php?nid=116285&md5_url=2150b333756e64325bdbc4a5fd45fad1") {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let decoder = JSONDecoder()
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
        decoder.dateDecodingStrategy = .formatted(dateFormatter)
        if let data = data, let masks = try? decoder.decode([Mask].self, from: data) {
            print(masks.first)
        }
    }.resume()
}

personalizado

Ejemplo: API Dcard.

https://dcard.tw/_api/posts?popular=true

Afortunadamente, el SDK de iOS proporciona ISO8601DateFormatter para ayudar a analizar iso8601 con un punto decimal. Sin embargo, ISO8601DateFormatter no es un DateFormatter, no podemos pasar el objeto ISO8601DateFormatter en .formatted ().

Por lo tanto, solo podemos usar el truco asesino, confiando en el último método, escribir el programa de análisis de tiempo con cierre, a través del caso personalizado de DateDecodingStrategy.

struct Dcard: Decodable {
    let title: String
    let createdAt: Date
}
if let url = URL(string: "https://dcard.tw/_api/posts?popular=true") {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let decoder = JSONDecoder()
        let dateFormatter = ISO8601DateFormatter()
        dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
        decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
            let container = try decoder.singleValueContainer()
            let dateString = try container.decode(String.self)
            if let date = dateFormatter.date(from: dateString) {
                return date
            } else {
                throw DecodingError.dataCorruptedError(in: container, debugDescription: "")
            }
        })
        if let data = data, let dcards = try? decoder.decode([Dcard].self, from: data) {
            print(dcards.first)
        }
    }.resume()
}

      

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]

decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
   let container = try decoder.singleValueContainer()
   let dateString = try container.decode(String.self)
   if let date = dateFormatter.date(from: dateString) {
        return date
   } else {
        throw DecodingError.dataCorruptedError(in: container, debugDescription: "")
   }
})

Use withFractionalSeconds para analizar ISO 8601 segundos con decimales

Suggested posts

“Esa islita lo cambia todo”

Cómo diseñamos Lyft Live Activities para mejorar la experiencia del pasajero

“Esa islita lo cambia todo”

Un cambio de juego para los viajes compartidos De todas las cosas que hacemos en Lyft, coreografiar las recolecciones entre pasajeros y conductores es una de las más complejas y trascendentales. Lograr esta coreografía depende de que Lyft haga muchas cosas bien, pero simplemente mantener a los pasajeros al día es esencial.

Ciclo de vida de la aplicación

Ciclo de vida de la aplicación

: Ciclo desde el inicio de la aplicación hasta el apagado: Usabilidad mediante la administración de memoria o datos ⬆️ La seguridad se puede procesar UIApplication, situación de AppDelegate: define las funciones que el objeto AppDelegate recibe el mensaje enviado desde el objeto UIApplication y ejecuta cada No en ejecución: el estado en el que la aplicación no se está ejecutandoInactivo: El estado en el que se ejecuta la aplicación pero no se reciben eventos. Activo: el estado en el que se ejecuta la aplicación y se produce un evento. Fondo: el estado en el que la aplicación se encuentra en segundo plano, pero el código se ejecuta. Suspendido: el estado en el que se encuentra la aplicación. en segundo plano y sin ejecutar código para delegar funciones en el archivo AppDelegate.swift SceneDelegate Para responder bien a la función de escena múltiple admitida desde iOS 13 en adelante AppDelegate / SceneDelegate AppDelegate 1.

Related posts

Financiamiento de la eliminación de carbono en el año fiscal 24

El desglose de las solicitudes de asignaciones de Carbon180 a través de vías

Financiamiento de la eliminación de carbono en el año fiscal 24

Por Alyson Lee, asesora de gestión de asuntos gubernamentales El proceso de asignaciones anuales del gobierno federal es fundamental para nuestros esfuerzos por financiar la eliminación de dióxido de carbono (CDR). Cada año, Carbon180 envía solicitudes a varias oficinas del Congreso para ayudar a guiar hacia dónde fluirán los dólares del próximo año.

Lo que puede hacer en su temporada de espera (esperando conseguir su primer trabajo en tecnología)

Lo que puede hacer en su temporada de espera (esperando conseguir su primer trabajo en tecnología)

Cambiar a una nueva carrera puede ser extremadamente desafiante si trata de hacerlo solo. Es importante encontrar socios responsables que estén en el mismo nivel de aprendizaje que usted, que compartan objetivos, tenacidad e impulso similares.

El asesinato de Jordan Neely y el problema del racismo “patriótico”

¿Puede Estados Unidos dar el paso esencial de no equiparar el comportamiento racista con ser un buen estadounidense?

El asesinato de Jordan Neely y el problema del racismo “patriótico”

[Alerta de activación: este ensayo incluye capturas de pantalla de personas que elogiaron al asesino de Jordan Neely.] Los funcionarios encargados de hacer cumplir la ley finalmente, y quizás a regañadientes, acusaron a Daniel Penny, el hombre que estranguló a Jordan Neely hasta que murió, por ese homicidio.

La semana de aprendizaje en el trabajo es más importante de lo que piensas

La semana de aprendizaje en el trabajo es más importante de lo que piensas

A menudo nos encontramos luchando para implementar lo que sabemos que es bueno para nosotros. Desde decirle a un ser querido que lo amamos hasta recordar hablar como un pirata, siempre habrá quienes digan que no hace falta un día, una semana o un mes de eventos porque ya están haciendo esas cosas.