Skip to content

Commit

Permalink
Adds ISO8601WithFractionalSecondsStrategy
Browse files Browse the repository at this point in the history
  • Loading branch information
marksands committed Jul 10, 2021
1 parent e9ce48f commit 6115317
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Sources/BetterCodable/ISO8601WithFractionalSecondsStrategy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation

/// Decodes `String` values as an ISO8601 `Date`.
///
/// `@ISO8601Date` relies on an `ISO8601DateFormatter` in order to decode `String` values into `Date`s. Encoding the `Date`
/// will encode the value into the original string value.
///
/// For example, decoding json data with a `String` representation of `"1996-12-19T16:39:57-08:00"` produces a valid `Date`
/// representing 39 minutes and 57 seconds after the 16th hour of December 19th, 1996 with an offset of -08:00 from UTC
/// (Pacific Standard Time).
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
public struct ISO8601WithFractionalSecondsStrategy: DateValueCodableStrategy {
private static let formatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()

public static func decode(_ value: String) throws -> Date {
guard let date = Self.formatter.date(from: value) else {
throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Invalid Date Format!"))
}
return date
}

public static func encode(_ date: Date) -> String {
return Self.formatter.string(from: date)
}
}
20 changes: 19 additions & 1 deletion Tests/BetterCodableTests/DateValueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,25 @@ class CustomDateCodableValueTests: XCTestCase {
let fixture = try JSONDecoder().decode(Fixture.self, from: jsonData)
XCTAssertEqual(fixture.iso8601, Date(timeIntervalSince1970: 851042397))
}


@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
func testDecodingAndEncodingISO8601DateStringWithFractionalSeconds() throws {
struct Fixture: Codable {
@DateValue<ISO8601WithFractionalSecondsStrategy> var iso8601: Date
@DateValue<ISO8601WithFractionalSecondsStrategy> var iso8601Short: Date
}
let jsonData = """
{
"iso8601": "1996-12-19T16:39:57.123456Z",
"iso8601Short": "1996-12-19T16:39:57.000Z-08:00"
}
""".data(using: .utf8)!

let fixture = try JSONDecoder().decode(Fixture.self, from: jsonData)
XCTAssertEqual(fixture.iso8601Short, Date(timeIntervalSince1970: 851013597.0))
XCTAssertEqual(fixture.iso8601, Date(timeIntervalSince1970: 851013597.123))
}

func testDecodingAndEncodingRFC3339DateString() throws {
struct Fixture: Codable {
@DateValue<RFC3339Strategy> var rfc3339Date: Date
Expand Down

0 comments on commit 6115317

Please sign in to comment.