quicktype icon indicating copy to clipboard operation
quicktype copied to clipboard

Support date/time types in all target languages

Open schani opened this issue 7 years ago • 11 comments

  • [x] Swift
  • [ ] Go
  • [ ] JavaScript/TypeScript/Flow
  • [ ] C++
  • [ ] Rust
  • [ ] Java
  • [ ] Elm
  • [ ] Dart
  • [ ] Kotlin
  • [ ] Objective-C
  • [ ] Ruby

Swift

https://useyourloaf.com/blog/swift-codable-with-custom-dates/ https://stackoverflow.com/questions/46537790/iso8601-date-json-decoding-using-swift4

schani avatar Dec 05 '17 15:12 schani

I would like to second that with the addition of C#.

mattbudish avatar Dec 05 '17 17:12 mattbudish

@mattbudish The reason C# is not on the list is because it's already implemented ;-)

schani avatar Dec 05 '17 22:12 schani

I've made this for Swift but it uses the same dateDecodingStrategy for the whole JSON data and need to be passed at top of structure init even that date properties are in deeper structures inside the original JSON, hope it helps:

func newJSONDecoder(dateFormatter: DateFormatter? = nil) -> JSONDecoder {
    let decoder = JSONDecoder()
    if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
        if let formatter = dateFormatter {
            decoder.dateDecodingStrategy = .formatted(formatter)
        } else {
            decoder.dateDecodingStrategy = .iso8601
        }
    }
    return decoder
}
struct LeafElement: Codable {
    let startDate: Date?
    
    static var dateFormatter: DateFormatter {
        return DateFormatter(withFormat: Constants.defaultDateFormat,
                             locale: Locale.current.languageCode ?? Constants.defaultLocale
        )
    }
extension Array where Element == RootJsonElement.Element {
    init(data: Data) throws {
        self = try newJSONDecoder(dateFormatter: LeafElement.dateFormatter).decode(LeafElement.self, from: data)
    }

buguibu avatar Aug 23 '18 07:08 buguibu

@buguibu We already have date-time in Swift. I didn't update this issue - sorry about that.

https://app.quicktype.io?share=1O1VFdIVOTzAjHHk4YkA

schani avatar Aug 23 '18 13:08 schani

@schani i see the option but it didn´t work for me with formts like "yyyy-MM-dd"

buguibu avatar Aug 23 '18 14:08 buguibu

@buguibu Sorry for getting back to you so late.

The problem is that Swift doesn't parse that date format - try it out in a playground:

// To parse the JSON, add this file to your project and do:
//
//   let pokedex = try Pokedex(json)

import Foundation

struct Pokedex: Codable {
    let foo: Date
}

// MARK: Convenience initializers and mutators

extension Pokedex {
    init(data: Data) throws {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        self = try decoder.decode(Pokedex.self, from: data)
    }
    
    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }
    
    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }
    
    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }
    
    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

let p = try Pokedex("{ \"foo\": \"2000-12-31\" }", using: .utf8)

It works with this, for example:

let p = try Pokedex("{ \"foo\": \"2099-12-31T08:00:00Z\" }", using: .utf8)

If you know a solution, please let us know.

schani avatar Aug 29 '18 03:08 schani

  • [x] Dart

Added Dart support via #1203

ozum avatar Apr 11 '19 06:04 ozum

For Swift, the default/newJSONDecoder decoder did not work for me so I had to implement the dateDecodingStrategy myself. Some people might find it helpful so I have demonstrated it below:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom {
    decoder in
    let container = try decoder.singleValueContainer()
    let dateString = try container.decode(String.self)
    
    let formatter = DateFormatter()
    let formats = [
        "yyyy-MM-dd HH:mm:ss",
        "yyyy-MM-dd",
        "yyyy-MM-dd HH:mm:ss.SSS ZZZ",
        "yyyy-MM-dd HH:mm:ss ZZZ" // 1997-09-15 07:00:00 UTC
    ]
    
    for format in formats {
        formatter.dateFormat = format
        if let date = formatter.date(from: dateString) {
            return date
        }
    }
    
    let iso = ISO8601DateFormatter()
    iso.timeZone = TimeZone(abbreviation: "UTC")
    if let date = iso.date(from: dateString) {
        return date
    }
    
    if let date = ISO8601DateFormatter().date(from: dateString) {
        return date
    }
    
    throw DecodingError.dataCorruptedError(in: container,
                                           debugDescription: "Cannot decode date string \(dateString)")
}

do {
    _ = try decoder.decode(Coordinate.self, from: data)
} catch let decodeError {
    print(decodeError)
}

It might be useful to allow extra date formats

twodayslate avatar Aug 13 '19 15:08 twodayslate

hello, I wanted to put a vote in for objective-c. I presently have to make a category for each class so I can parse dates. Tried to take a look at doing it myself / making a pull request, but I think I got a bit in over my head. If you had any thoughts on an approach, perhaps I could make it happen!

davidhodge avatar Jun 06 '20 04:06 davidhodge

hello, i want to implement this for Go, anyone already working on that?, from what I can see it should be pretty trivial

nk2580 avatar Nov 05 '20 23:11 nk2580

Any idea when the Go change might be merged? Tried it out and works well, would love to see it added

rekram1-node avatar Aug 16 '23 00:08 rekram1-node