Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

399
Vistas
Vapor pass date parameter

In my Vapor 3 app, I have an Event model, which has the properties startDate: Date and endDate: Date.
Now, I'm wondering how to pass those date values in a POST request. In Postman, I tried the following in x-www-form-urlencoded:

startDate -> 2019-03-14

This returns the error below:

Could not convert to Double: str(\"2019-03-14\")

Apparently, Date turns into Double.
So, instead, what value do I need to pass?


Note

I know, that, in Postman, I can insert {{$timestamp}}, but 1) this doesn't answer my question when using the API outside Postman and 2) this doesn't allow me to enter a date other than now.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

So the issue here is that by default, a Date instance is decoded using the time interval since Jan 1, 2001. The URL form decoder that Vapor uses doesn't support different date strategies like the JSONDecoder does at the moment, so you'll have to do the decoding a different way. Here are a couple of ideas I could come up with:

  • Just send the timestamp in the request. For testing different dates in Postman, you can set an environment variable in the pre-request script and access that in the request body.
  • Manually implement the Event.init(from:) and .encode(to:) methods. Just to make sure you don't break the Fluent coding, you will probably have to add some extra logic, but it should work. Here's an example:

    final class Event: Model {
        static let formDateFormatter: DateFormatter = {
            let formatter = DateFormatter()
            formatter.calendar = Calendar(identifier: .iso8601)
            formatter.locale = Locale(identifier: "en_US_POSIX")
            formatter.timeZone = TimeZone(secondsFromGMT: 0)
            formatter.dateFormat = "yyyy-MM-dd"
            return formatter
        }()
    
        var startDate: Date
        var endDate: Date
    
        init(from decoder: Decoder)throws {
            let container = try decoder.container(keyedby: CodingKeys.self)
    
            if let start = try? container.decode(String.self, keyedBy: .startDate), let date = Event.formDateFormatter.string(from: start) {
                self.startDate = date
            } else {
                self.startDate = try container.decode(Date.self, keyedBy: .startDate)   
            }
    
            if let end = try? container.decode(String.self, keyedBy: .endDate), let date = Event.formDateFormatter.string(from: end) {
                self.endDate = date
            } else {
                self.endDate = try container.decode(Date.self, keyedBy: .endDate)   
            }
        }
    }
    
over 4 years ago · Santiago Trujillo Denunciar

0

I'm not sure about x-www-form-urlencoded cause I tested it and if I send a date as 0 it decodes it as 2001-01-01 00:00:00 +0000 thought it definitely should be 1970-01-01 00:00:00 +0000.

But with JSON payload you have a flexibility cause you could provide a JSONDecoder configured as needed for you.

struct Payload: Content {
    var date: Date
}

If you'd like to send dates as UNIX-timestamp

router.post("check") { req throws -> Future<String> in
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .secondsSince1970 // choose it for unix-timestamp
    return try req.content.decode(json: Payload.self, using: decoder).map { p in
        return String(describing: p.date)
    }
}

If you'd like to send dates in your own format

router.post("check") { req throws -> Future<String> in
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(formatter) // custom date formatter
    return try req.content.decode(json: Payload.self, using: decoder).map { p in
        return String(describing: p.date)
    }
}

So for unix-timestamp you should send seconds from 1970 and e.g. 0 will be decoded to 1970-01-01 00:00:00 +0000.

And for custom format described above you should send dates like 2018-01-01 00:00:00 to decode it as 2018-01-01 00:00:00 +0000

UPD: you could write an extension to decode it beautifully

extension ContentContainer where M: Request {
    func decodeJson<D>(_ payload: D.Type) throws -> Future<D> where D: Decodable {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .formatted(formatter)
        return try decode(json: payload, using: decoder)
    }
}

so then you'll be able to decode your payload like this

router.post("check") { (req) throws -> Future<String> in
    return try req.content.decodeJson(Payload.self).map { p in
        return String(describing: p.date)
    }
}
over 4 years ago · Santiago Trujillo Denunciar

0

I realized that the Date object is returned in the following format when queried:

2021-12-31T14:29:00Z

So this is what I tried to pass and that worked! No need for any custom decoding.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda