I’m struggling to understand how best to represent dates and ensure they can be encoded and decoded consistently between Service and Client when both the service and client and written in Swift.
For context, my server is written using Vapor, Fluent, Graphiti, and GraphQLSwift. My client is using Apollo for iOS.
It’s my understanding that I need to create a custom scalar type when defining the schema which I’ve done using Scalar(Date.self)
in my schema definition.
On my server side my models have date fields like @Field(key: "date_purchased") var datePurchased: Date?
. The data is stored in the database (Postgres) as a timestamp with timezone
field.
When I test the server in a GraphQL playground my date field looks like "datePurchased": 1704407422,
which appears to be a double value that seems to be a UNIX timestamp.
On the client side (Apollo) I create a custom schema type:
public extension ClientAPI {
typealias Date = String
}
extension Foundation.Date: CustomScalarType {
public init(_jsonValue value: JSONValue) throws {
guard let dateString = value as? String else {
throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
}
guard let date = ISO8601DateFormatter().date(from: dateString) else {
throw JSONDecodingError.couldNotConvert(value: value, to: Date.self)
}
self = date
}
public var _jsonValue: JSONValue {
self.timeIntervalSince1970
}
}
Also, I noticed if I used the fluent @Timestamp property wrapper @Timestamp(key: "created_at", on: .create) var dateCreated: Date?
and view this in the playground it pulls through as "dateCreated": 1705619227.214435
with decimal places?
What is the best way to reliably manage date formats between client and server when both are using Swift’s Foundation.Date? Is it possible to use other date formats in the external API other than UNIX timestamps?