蒸汽通过日期参数

问题描述 投票:1回答:2

在我的Vapor 3应用程序中,我有一个Event模型,它具有startDate: DateendDate: Date属性。 现在,我想知道如何在POST请求中传递这些日期值。在Postman中,我在x-www-form-urlencoded中尝试了以下内容:

startDate -> 2019-03-14

这将返回以下错误:

无法转换为Double:str(\“2019-03-14 \”)

显然,Date变成了Double。 那么,相反,我需要传递什么价值?


Note

我知道,在邮递员中,我可以插入{{$timestamp}},但是1)在Postman之外使用API​​时这不回答我的问题2)这不允许我输入除现在以外的日期。

swift date vapor
2个回答
1
投票

我不确定x-www-form-urlencoded因为我测试了它,如果我发送日期作为0它解码它2001-01-01 00:00:00 +0000认为它肯定应该是1970-01-01 00:00:00 +0000

但是使用JSON有效负载,您可以提供灵活性,因为您可以根据需要提供配置的JSONDecoder

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)
    }
}

因此,对于unix-timestamp,您应该从1970年开始发送秒数,例如0将被解码为1970-01-01 00:00:00 +0000

对于上面描述的自定义格式,您应该发送像2018-01-01 00:00:00这样的日期,将其解码为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)
    }
}

那么你就能像这样解码你的有效载荷

router.post("check") { (req) throws -> Future<String> in
    return try req.content.decodeJson(Payload.self).map { p in
        return String(describing: p.date)
    }
}

1
投票

所以这里的问题是默认情况下,使用自2001年1月1日以来的时间间隔对Date实例进行解码.Vapor使用的URL form decoder不支持JSONDecoder目前所做的不同日期策略,所以你必须以不同的方式进行解码。以下是我可以提出的一些想法:

  • 只需在请求中发送时间戳。要在Postman中测试不同的日期,您可以在预请求脚本中设置环境变量,并在请求正文中访问该环境变量。
  • 手动实现Event.init(from:).encode(to:)方法。只是为了确保你不打破Fluent编码,你可能需要添加一些额外的逻辑,但它应该工作。这是一个例子: 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) } } }
© www.soinside.com 2019 - 2024. All rights reserved.