vapor / fluent-mysql-driver

🖋🐬 Swift ORM (queries, models, relations, etc) built on MySQL.
MIT License
77 stars 52 forks source link

Could not convert MySQL data to Date on time field #221

Open eugeniobaglieri opened 1 year ago

eugeniobaglieri commented 1 year ago

Hi, I'm trying to save the time giving a swift date object. I'm not getting any error on save and the time is saved without errors. But when I try to query this model I get this error:

invalid field: 'opening_time', type: Date, error: typeMismatch(Foundation.Date, Swift.DecodingError.Context(codingPath: [], debugDescription: "Could not convert MySQL data to Date: <MYSQL_TYPE_TIME>", underlyingError: nil)) [request-id: C9E79175-5642-4AF1-B362-5FFDF0F9F077] (App/ErrorMiddleware.swift:63)

I defined this model:

final class Club: Model {

    static var schema: String { "clubs" }

    @ID(key: .id)
    var id: UUID?

    @Field(key: "name")
    var name: String

    @Field(key: "contact")
    var contact: String

    @Field(key: "address")
    var address: String

    @Field(key: "latitude")
    var latitude: Double

    @Field(key: "longitude")
    var longitude: Double

    @Children(for: \.$club)
    var playgrounds: [Playground]

    @OptionalChild(for: \.$club)
    var user: User?

    @Field(key: "active")
    var active: Bool

    @Field(key: "opening_time")
    var openingTime: Date

    @Field(key: "closing_time")
    var closingTime: Date

    @Field(key: "time_slot_duration")
    var timeSlotDuration: Int

    @Timestamp(key: "created_at", on: .create)
    var createdAt: Date?

    @Timestamp(key: "updated_at", on: .update)
    var updatedAt: Date?

    init() {}
}

with this schema:

func prepare(on database: Database) async throws {
        try await database.schema(Club.schema)
            .id()
            .field("name", .string, .required)
            .field("contact", .string, .required)
            .field("address", .string, .required)
            .field("latitude", .double, .required)
            .field("longitude", .double, .required)
            .field("opening_time", .time, .required)
            .field("closing_time", .time, .required)
            .field("time_slot_duration", .int, .required)
            .field("active", .bool, .required, .sql(.default(true)))
            .field("created_at", .datetime, .required)
            .field("updated_at", .datetime)
            .create()
    }

On query i should obtain an object with populated openingTime and closingTime

Environment

0xTim commented 1 year ago

Yeah the trouble is there is no good way to represent time in Swift (the same applies to date fields as well). I'm not sure what the best suggested solution to this is, but maybe @gwynne can advise.

Each time this comes up I'm of the mind we should create our own types for only date and only time but there are a lot of edge cases