Objectmapper: Странное поведение при преобразовании даты

Созданный на 14 дек. 2016  ·  3Комментарии  ·  Источник: tristanhimmelman/ObjectMapper

Привет,

Раньше эта библиотека использовалась для простого преобразования дат без необходимости указывать функцию преобразования даты (по крайней мере, это поведение, которое я видел).

Так например

public private(set) var myDate:Date?

public fund mapping(map: Map) {
  myDate <- map["my_date"]
}

Учитывая, что дата имеет формат «2016-12-09T13: 37: 27.262Z», она преобразует эту дату должным образом без необходимости указывать, что это действительно дата.

Моя текущая модель по какой-то причине не может правильно проанализировать дату. Я пробовал оба примера, приведенные в read-me, я рассмотрел "закрытые" проблемы, касающиеся форматирования даты, и я также попытался использовать их примеры ... все равно не повезло.

Я пробовал эти преобразования даты

  1. DateTransform ()
  2. Функция преобразования даты ISO

Мой модульный тест ...

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

который производит ...

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

Ясно, что дата, которую я даю, не 1970 ... и дата, указанная выше, действительно является датой в формате ISO. Я использую сервер Express / Mongo, и я просто использую javascript-вызов Date.now для генерации даты. Кроме того, схема в модели Mongo имеет тип Date.

Вот моя модель поездки

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

Опять же, как указано выше, я пробовал использовать как DateTransform (), так и ISO8601DateTransform ().

Если я использую функцию DateTransform, мой модульный тест «пройдет», потому что свойство date больше не будет равным нулю, но это будет дата 1970 года, что неверно.

Если я использую ISO8601DateTransform, свойство равно нулю, и модульный тест завершится неудачно, потому что ожидалось, что дата не будет нулем.

Раньше я просто указывал, что это свойство было «датой», и оно все преобразует правильно, без необходимости специально устанавливать кортеж DateTransform для сопоставления. Я точно не знаю, что делаю здесь неправильно.

==== Обновлен, чтобы он выглядел красивее =====

Самый полезный комментарий

Так что я считаю, что, возможно, решил свою проблему ...

Я до сих пор не знаю, почему встроенный форматировщик даты ISO не работает, но я создал свой

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

похоже, это работает нормально, теперь модульные тесты проходят с действительными датами.

Все 3 Комментарий

Так что я считаю, что, возможно, решил свою проблему ...

Я до сих пор не знаю, почему встроенный форматировщик даты ISO не работает, но я создал свой

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

похоже, это работает нормально, теперь модульные тесты проходят с действительными датами.

Просто чтобы добавить к этому. Я не мог заставить вышеперечисленное решение работать, но оно действительно направило меня в правильное русло, и я так ценю его. Я внес некоторые изменения, и это работает для меня.

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

Другое исправление:
https://forums.swift.org/t/iso8601dateformatter-fails-to-parse-a-valid-iso-8601-date/22999/12

открытый класс ISODateTransform: TransformType {
public typealias Object = Date
общедоступный 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
}

}

Была ли эта страница полезной?
0 / 5 - 0 рейтинги