Skip to content

Commit

Permalink
fix: date formatter breaking change (#435)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored Jul 1, 2024
1 parent fea42cf commit 6b4cc2e
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 40 deletions.
14 changes: 9 additions & 5 deletions Sources/Auth/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@
// Created by Guilherme Souza on 14/12/23.
//

import ConcurrencyExtras
import Foundation
import Helpers

extension AuthClient.Configuration {
private static let supportedDateFormatters: [UncheckedSendable<ISO8601DateFormatter>] = [
ISO8601DateFormatter.iso8601WithFractionalSeconds,
ISO8601DateFormatter.iso8601,
]

/// The default JSONEncoder instance used by the ``AuthClient``.
public static let jsonEncoder: JSONEncoder = {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.dateEncodingStrategy = .custom { date, encoder in
let string = ISO8601DateFormatter.iso8601WithFractionalSeconds.value.string(from: date)
var container = encoder.singleValueContainer()
let string = DateFormatter.iso8601.string(from: date)
try container.encode(string)
}
return encoder
Expand All @@ -29,10 +35,8 @@ extension AuthClient.Configuration {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)

let supportedFormatters: [DateFormatter] = [.iso8601, .iso8601_noMilliseconds]

for formatter in supportedFormatters {
if let date = formatter.date(from: string) {
for formatter in supportedDateFormatters {
if let date = formatter.value.date(from: string) {
return date
}
}
Expand Down
17 changes: 8 additions & 9 deletions Sources/Helpers/AnyJSON/AnyJSON+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@ extension AnyJSON {
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)

let date = DateFormatter.iso8601.date(from: dateString) ?? DateFormatter
.iso8601_noMilliseconds.date(from: dateString)
let date = ISO8601DateFormatter.iso8601WithFractionalSeconds.value.date(from: dateString) ?? ISO8601DateFormatter.iso8601.value.date(from: dateString)

guard let decodedDate = date else {
throw DecodingError.typeMismatch(
Date.self,
DecodingError.Context(
codingPath: container.codingPath,
debugDescription: "String is not a valid Date"
)
throw DecodingError.dataCorruptedError(
in: container, debugDescription: "Invalid date format: \(dateString)"
)
}

Expand All @@ -38,7 +33,11 @@ extension AnyJSON {
public static let encoder: JSONEncoder = {
let encoder = JSONEncoder()
encoder.dataEncodingStrategy = .base64
encoder.dateEncodingStrategy = .formatted(DateFormatter.iso8601)
encoder.dateEncodingStrategy = .custom { date, encoder in
let string = ISO8601DateFormatter.iso8601WithFractionalSeconds.value.string(from: date)
var container = encoder.singleValueContainer()
try container.encode(string)
}
return encoder
}()
}
Expand Down
27 changes: 10 additions & 17 deletions Sources/Helpers/DateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,19 @@
// Created by Guilherme Souza on 28/12/23.
//

import ConcurrencyExtras
import Foundation

extension DateFormatter {
/// DateFormatter class that generates and parses string representations of dates following the
/// ISO 8601 standard
package static let iso8601: DateFormatter = {
let iso8601DateFormatter = DateFormatter()

iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
iso8601DateFormatter.locale = Locale(identifier: "en_US_POSIX")
iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return iso8601DateFormatter
extension ISO8601DateFormatter {
package static let iso8601: UncheckedSendable<ISO8601DateFormatter> = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime]
return UncheckedSendable(formatter)
}()

package static let iso8601_noMilliseconds: DateFormatter = {
let iso8601DateFormatter = DateFormatter()

iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
iso8601DateFormatter.locale = Locale(identifier: "en_US_POSIX")
iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return iso8601DateFormatter
package static let iso8601WithFractionalSeconds: UncheckedSendable<ISO8601DateFormatter> = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return UncheckedSendable(formatter)
}()
}
2 changes: 1 addition & 1 deletion Sources/Helpers/SupabaseLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public struct SupabaseLogMessage: Codable, CustomStringConvertible, Sendable {
}

public var description: String {
let date = DateFormatter.iso8601_noMilliseconds.string(from: Date(timeIntervalSince1970: timestamp))
let date = ISO8601DateFormatter.iso8601.value.string(from: Date(timeIntervalSince1970: timestamp))
let file = fileID.split(separator: ".", maxSplits: 1).first.map(String.init) ?? fileID
var description = "\(date) [\(level)] [\(system)] [\(file).\(function):\(line)] \(message)"
if !additionalContext.isEmpty {
Expand Down
9 changes: 5 additions & 4 deletions Sources/PostgREST/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
// Created by Guilherme Souza on 14/12/23.
//

import ConcurrencyExtras
import Foundation
import Helpers

let version = Helpers.version

extension PostgrestClient.Configuration {
private static let supportedDateFormatters: [DateFormatter] = [
.iso8601,
.iso8601_noMilliseconds,
private static let supportedDateFormatters: [UncheckedSendable<ISO8601DateFormatter>] = [
ISO8601DateFormatter.iso8601WithFractionalSeconds,
ISO8601DateFormatter.iso8601,
]

/// The default `JSONDecoder` instance for ``PostgrestClient`` responses.
Expand All @@ -24,7 +25,7 @@ extension PostgrestClient.Configuration {
let string = try container.decode(String.self)

for formatter in supportedDateFormatters {
if let date = formatter.date(from: string) {
if let date = formatter.value.date(from: string) {
return date
}
}
Expand Down
28 changes: 28 additions & 0 deletions Tests/PostgRESTTests/JSONTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// JSONTests.swift
//
//
// Created by Guilherme Souza on 01/07/24.
//

@testable import PostgREST
import XCTest

final class JSONTests: XCTestCase {
func testDecodeJSON() throws {
let json = """
{
"created_at": "2024-06-15T18:12:04+00:00"
}
""".data(using: .utf8)!

struct Value: Decodable {
var createdAt: Date

enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
}
}
_ = try PostgrestClient.Configuration.jsonDecoder.decode(Value.self, from: json)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/gtm-session-fetcher.git",
"state" : {
"revision" : "0382ca27f22fb3494cf657d8dc356dc282cd1193",
"version" : "3.4.1"
"revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b",
"version" : "3.5.0"
}
},
{
Expand Down Expand Up @@ -77,8 +77,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-crypto.git",
"state" : {
"revision" : "bc1c29221f6dfeb0ebbfbc98eb95cd3d4967868e",
"version" : "3.4.0"
"revision" : "33f65a3cbc52f8c19295723af9cbecc2195484e1",
"version" : "3.5.0"
}
},
{
Expand Down

0 comments on commit 6b4cc2e

Please sign in to comment.