Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

401
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda