swagger-api / swagger-api/swagger-codegen
[Swift4] ParseError, "Date string does not match format expected by formatter." when date string has not miliseconds
Open
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
When CodableHelper decode a model with date, if that Date String hasn't milisecond (ex. "2019-02-14T00:00:00") the decoder throws a decode error.
Swagger-codegen version
tag -> 2.4.1 and later
Swagger declaration file content or url
ModelV2:
type: object
properties:
Name:
type: string
Url:
type: string
Description:
type: string
StartDate:
format: date-time
type: string
EndDate:
format: date-time
type: string
Type:
enum:
- XXXXType
- XXXXType2
type: string
Size:
type: string
Order:
format: int32
type: integer
Steps to reproduce
Parse this model throws decode error:
{
"Name": "XXXXXXX",
"Url": "https://XXXXXX",
"Description": "XXXXXDescription",
"StartDate": "2019-02-14T00:00:00",
"EndDate": "2019-02-28T00:00:00",
"Type": "XXXXType",
"Size": "375x255",
"Order": 1
}
Suggest a fix/enhancement
I propouse this fix on CodableHelper.swift
Actual Code
open class func decode<T>(_ type: T.Type, from data: Data) -> (decodableObj: T?, error: Error?) where T : Decodable {
var returnedDecodable: T? = nil
var returnedError: Error? = nil
let decoder = JSONDecoder()
if let df = self.dateformatter {
decoder.dateDecodingStrategy = .formatted(df)
} else {
decoder.dataDecodingStrategy = .base64
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'T'HH:mm:ss.SSSXXXXX"
decoder.dateDecodingStrategy = .formatted(formatter)
}
do {
returnedDecodable = try decoder.decode(type, from: data)
} catch {
returnedError = error
}
return (returnedDecodable, returnedError)
}
New fix Code
open class func decode<T>(_ type: T.Type, from data: Data) -> (decodableObj: T?, error: Error?) where T : Decodable {
var returnedDecodable: T? = nil
var returnedError: Error? = nil
let decoder = JSONDecoder()
if let df = self.dateformatter {
decoder.dateDecodingStrategy = .formatted(df)
} else {
decoder.dataDecodingStrategy = .base64
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateStr = try container.decode(String.self)
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'T'HH:mm:ss.SSSXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
if let date = formatter.date(from: dateStr) {
return date
}
throw DateError.invalidDate
})
}
do {
returnedDecodable = try decoder.decode(type, from: data)
} catch {
returnedError = error
}
return (returnedDecodable, returnedError)
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in CodableHelper.swift and reproduce the failure with the supplied ModelV2 JSON, comparing date strings with and without milliseconds. Done means the decoder accepts the shown date-time values without a decode error while preserving the existing custom date formatter behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100