Skip to content

Commit

Permalink
Extend date decoding strategy for possible fractional seconds (#35)
Browse files Browse the repository at this point in the history
* Add support for fractional seconds in dates

If the WriteFreely instance returns dates with fractional seconds (e.g., 2022-09-28T11:55:39.886581893Z), the date-decoding strategy fails and an error is thrown.

* Switch formatOptions depending on fractional seconds

* Bump minimum OS versions
  • Loading branch information
AngeloStavrow authored Oct 5, 2022
1 parent f700e05 commit 0361ed3
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import PackageDescription
let package = Package(
name: "WriteFreely",
platforms: [
.macOS(.v10_12),
.iOS(.v10)
.macOS(.v10_13),
.iOS(.v11)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
Expand Down
33 changes: 33 additions & 0 deletions Sources/WriteFreely/Extensions/JSONDecoder+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Credit: https://github.com/vapor/vapor/issues/2481#issuecomment-702013846

import Foundation

extension JSONDecoder.DateDecodingStrategy {

/// The strategy that formats dates according to the ISO 8601 standard.
/// - Note: This includes the fractional seconds, unlike the standard `.iso8601`, which fails to decode those.
static var iso8601WithPossibleFractionalSeconds: JSONDecoder.DateDecodingStrategy {
JSONDecoder.DateDecodingStrategy.custom { (decoder) in
let singleValue = try decoder.singleValueContainer()
let dateString = try singleValue.decode(String.self)

let formatter = ISO8601DateFormatter()

/// Use the `.withFractionalSeconds` option only if we have fractional seconds in the date string.
if dateString.contains(".") {
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
} else {
formatter.formatOptions = [.withInternetDateTime]
}

guard let date = formatter.date(from: dateString) else {
throw DecodingError.dataCorruptedError(
in: singleValue,
debugDescription: "Failed to decode string to ISO 8601 date."
)
}
return date
}
}

}
2 changes: 1 addition & 1 deletion Sources/WriteFreely/WFClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class WFClient {
/// - session: The URL session to use for connections; defaults to `URLSession.shared`.
public init(for instanceURL: URL, with session: URLSessionProtocol = URLSession.shared) {
decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
decoder.dateDecodingStrategy = .iso8601WithPossibleFractionalSeconds

self.session = session

Expand Down

0 comments on commit 0361ed3

Please sign in to comment.