Hello,
Before this library used to just transform dates without having to specify a date transform function (at least this is the behavior I saw).
So for example
public private(set) var myDate:Date?
public fund mapping(map: Map) {
myDate <- map["my_date"]
}
Given the date is of format "2016-12-09T13:37:27.262Z", it would transform this date properly without me having to specify that it was indeed a date.
My current model is failing to parse the date correctly for some reason. I've tried both the example given on the read-me, I've looked at the "closed" issues regarding date formatting and I've tried to use their examples as well...still no luck.
Ive tried these date transforms
My unit test...
class TripTests: XCTestCase {
func testInflateTestObjectFromJSON() {
var tripObj = [String:AnyObject]()
tripObj["_id"] = "123" as AnyObject?
tripObj["dropoff_time"] = "2016-12-09T13:37:27.262Z" as AnyObject?
let trip = Trip(JSON: tripObj)
XCTAssertNotNil(trip?.id)
XCTAssertNotNil(trip?.dropoffTime)
print(trip?.pickupTime)
print(trip?.dropoffTime)
dump(trip?.toJSONString())
}
}
which produces...
Optional(1970-01-01 00:33:36 +0000)
Optional(1970-01-01 00:33:36 +0000)
â–¿ Optional("{\"dropoff_time\":2016,\"pickup_time\":2016,\"_id\":\"123\"}")
Clearly, the date I'm giving it isn't 1970...and the above date is indeed an ISO formatted date. The server I'm running is Express/Mongo and I'm simply using the Date.now javascript call to generate a date. Also, the Schema on the Mongo model is of type 'Date'.
Here is my Trip model
import Foundation
import ObjectMapper
public class Trip : Mappable {
public private(set) var id: String?
public var pickupTime:Date?
public var dropoffTime:Date?
public var completed:Bool?
public private(set) var createdAt:Date?
public private(set) var updatedAt:Date?
public init(captain: User?, passenger: User?) {
self.captain = captain
self.passenger = passenger
}
public required init?(map: Map) {
}
public func mapping(map: Map) {
id <- map["_id"]
pickupTime <- (map["pickup_time"], DateTransform())
dropoffTime <- (map["dropoff_time"], DateTransform())
completed <- map["completed"]
updatedAt <- (map["updated_at"], DateTransform())
createdAt <- (map["created_at"], DateTransform())
}
}
Again, as stated above, I've tried using both the DateTransform() and the ISO8601DateTransform().
If I use the DateTransform function, my unit test will "pass" because the date property will no longer be nil however it will be the 1970 date which isn't correct.
If I use the ISO8601DateTransform, the property is nil and the unit test will fail because it was expecting the date to not be nil.
Before I would just specify that the property was a "date" and it would transform everything correctly without me having to specifically set a DateTransform tuple for the mapping. I don't know exactly what I am doing incorrectly here.
==== Updated just to make it look prettier =====
So I believe I may have solved my own issue...
I still do not know why the built in ISO date formatter doesn't work however I created my own
import Foundation
import ObjectMapper
open class ISODateTransform: TransformType {
public typealias Object = Date
public typealias JSON = String
public init() {}
public func transformFromJSON(_ value: Any?) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
guard let strValue = value as? String else { return nil }
return formatter.date(from: strValue)
}
public func transformToJSON(_ value: Date?) -> String? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
guard value != nil else { return nil }
return formatter.string(from: value!)
}}
this seems to work just fine, unit tests are passing with valid dates now.
Just to add to this. I couldn't get the solution above to work but it did steer me into the right directions so much appreciated. I made some tweaks and this works for me.
//
// ISODateTransform.swift
//
import Foundation
import ObjectMapper
open class ISODateTransform: TransformType {
public typealias Object = Date
public typealias JSON = String
public init() {}
public func transformFromJSON (_ value: Any?) -> Date? {
guard let datestring = value as? String else { return nil }
let isoFormatter = ISO8601DateFormatter()
let date = isoFormatter.date(from: datestring)!
return date
}
public func transformToJSON(_ value: Date?) -> String? {
let isoFormatter = ISO8601DateFormatter()
let string = isoFormatter.string(from: value!)
return string
}
}
Another Fix:
https://forums.swift.org/t/iso8601dateformatter-fails-to-parse-a-valid-iso-8601-date/22999/12
open class ISODateTransform: TransformType {
public typealias Object = Date
public typealias JSON = String
public init() {}
public func transformFromJSON (_ value: Any?) -> Date? {
guard let datestring = value as? String else { return nil }
let isoFormatter = ISO8601DateFormatter()
//Critical Fix
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let date = isoFormatter.date(from: datestring)!
return date
}
public func transformToJSON(_ value: Date?) -> String? {
let isoFormatter = ISO8601DateFormatter()
//Critical Fix
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let string = isoFormatter.string(from: value!)
return string
}
}
Most helpful comment
So I believe I may have solved my own issue...
I still do not know why the built in ISO date formatter doesn't work however I created my own
this seems to work just fine, unit tests are passing with valid dates now.