Repository: vapor/vapor
File: Sources/Vapor/URLEncodedForm/URLEncodedFormDecoder.swift (Swift)

Code before:
        var allKeys: [Key] {
            return self.data.children.keys.compactMap { Key(stringValue: String($0)) }
        }
        
        init(
            data: URLEncodedFormData,
            codingPath: [CodingKey],
            configuration: URLEncodedFormDecoder.Configuration
        ) {
            self.data = data
            self.codingPath = codingPath
            self.configuration = configuration
        }
        
        func contains(_ key: Key) -> Bool {
            return self.data.children[key.stringValue] != nil
        }
        
        func decodeNil(forKey key: Key) throws -> Bool {
            return self.data.children[key.stringValue] == nil
        }
        
        private func decodeDate(forKey key: Key) throws -> Date {
            //This error will only be thrown if no `dateDecodingStrategies` have been defined. It will get overwritten by the decoders' error if it's thrown
            var lastDecodingError: Error = DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "At least one date decoding strategy needs to be defined for `URLEncodedFormDecoder`. Use: ContentConfiguration.global.use(urlDecoder: URLEncodedFormDecoder(configuration: .init(dateDecodingStrategies: [.secondsSince1970])))"))
            for dateDecodingStrategy in configuration.dateDecodingStrategies {
                do {
                    return try decodeDate(forKey: key, as: dateDecodingStrategy)
                } catch {
                    lastDecodingError = error
                }
            }
            throw lastDecodingError
        }
        
        private func decodeDate(forKey key: Key, as dateFormat: URLEncodedFormDecoder.Configuration.DateDecodingStrategy) throws -> Date {
            //If we are trying to decode a required array, we might not have decoded a child, but we should still try to decode an empty array
            let child = self.data.children[key.stringValue] ?? []
            switch dateFormat {
            case .secondsSince1970:
                guard let value = child.values.last else {
                    throw DecodingError.valueNotFound(Date.self, at: self.codingPath + [key])
                }
                if let result = Date.init(urlQueryFragmentValue: value) {
                    return result
                } else {
                    throw DecodingError.typeMismatch(Date.self, at: self.codingPath + [key])
                }
            case .iso8601:
                let decoder = _Decoder(data: child, codingPath: self.codingPath + [key], configuration: configuration)
                if let date = ISO8601DateFormatter.threadSpecific.date(from: try String(from: decoder)) {

Review comment (refactor):
Foundation only supports a single date decoding strategy for their decoders (https://developer.apple.com/documentation/foundation/jsondecoder/2895216-datedecodingstrategy) and I think it would make sense to follow suit here. Otherwise we'd need to refactor this further since the way `lastDecodingError` is working, we're still throwing away errors. But I think supporting a single date decoding strategy is fine. If it works for Swift's standard JSON decoder it should work fine for Vapor's URL decoder, too. 

Code after:
        }
        
        init(
            data: URLEncodedFormData,
            codingPath: [CodingKey],
            configuration: URLEncodedFormDecoder.Configuration
        ) {
            self.data = data
            self.codingPath = codingPath
            self.configuration = configuration
        }
        
        func contains(_ key: Key) -> Bool {
            return self.data.children[key.stringValue] != nil
        }
        
        func decodeNil(forKey key: Key) throws -> Bool {
            return self.data.children[key.stringValue] == nil
        }
        
        private func decodeDate(forKey key: Key) throws -> Date {
            return try decodeDate(forKey: key, as: configuration.dateDecodingStrategy)
        }
        
        private func decodeDate(forKey key: Key, as dateFormat: URLEncodedFormDecoder.Configuration.DateDecodingStrategy) throws -> Date {
            //If we are trying to decode a required array, we might not have decoded a child, but we should still try to decode an empty array
            let child = self.data.children[key.stringValue] ?? []
            switch dateFormat {
            case .secondsSince1970:
                guard let value = child.values.last else {
                    throw DecodingError.valueNotFound(Date.self, at: self.codingPath + [key])
                }
                if let result = Date.init(urlQueryFragmentValue: value) {
                    return result
                } else {
                    throw DecodingError.typeMismatch(Date.self, at: self.codingPath + [key])
                }
            case .iso8601:
                let decoder = _Decoder(data: child, codingPath: self.codingPath + [key], configuration: configuration)
                if let date = ISO8601DateFormatter.threadSpecific.date(from: try String(from: decoder)) {
                    return date
                } else {
                    throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Unable to decode date. Expecting ISO8601 formatted date"))
                }
            case .custom(let callback):
                let decoder = _Decoder(data: child, codingPath: self.codingPath + [key], configuration: configuration)
                return try callback(decoder)
            }
        }
        
        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable {