Skip to content

Commit 6115317

Browse files
committed
Adds ISO8601WithFractionalSecondsStrategy
1 parent e9ce48f commit 6115317

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Foundation
2+
3+
/// Decodes `String` values as an ISO8601 `Date`.
4+
///
5+
/// `@ISO8601Date` relies on an `ISO8601DateFormatter` in order to decode `String` values into `Date`s. Encoding the `Date`
6+
/// will encode the value into the original string value.
7+
///
8+
/// For example, decoding json data with a `String` representation of `"1996-12-19T16:39:57-08:00"` produces a valid `Date`
9+
/// representing 39 minutes and 57 seconds after the 16th hour of December 19th, 1996 with an offset of -08:00 from UTC
10+
/// (Pacific Standard Time).
11+
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
12+
public struct ISO8601WithFractionalSecondsStrategy: DateValueCodableStrategy {
13+
private static let formatter: ISO8601DateFormatter = {
14+
let formatter = ISO8601DateFormatter()
15+
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
16+
return formatter
17+
}()
18+
19+
public static func decode(_ value: String) throws -> Date {
20+
guard let date = Self.formatter.date(from: value) else {
21+
throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Invalid Date Format!"))
22+
}
23+
return date
24+
}
25+
26+
public static func encode(_ date: Date) -> String {
27+
return Self.formatter.string(from: date)
28+
}
29+
}

Tests/BetterCodableTests/DateValueTests.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,25 @@ class CustomDateCodableValueTests: XCTestCase {
1111
let fixture = try JSONDecoder().decode(Fixture.self, from: jsonData)
1212
XCTAssertEqual(fixture.iso8601, Date(timeIntervalSince1970: 851042397))
1313
}
14-
14+
15+
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
16+
func testDecodingAndEncodingISO8601DateStringWithFractionalSeconds() throws {
17+
struct Fixture: Codable {
18+
@DateValue<ISO8601WithFractionalSecondsStrategy> var iso8601: Date
19+
@DateValue<ISO8601WithFractionalSecondsStrategy> var iso8601Short: Date
20+
}
21+
let jsonData = """
22+
{
23+
"iso8601": "1996-12-19T16:39:57.123456Z",
24+
"iso8601Short": "1996-12-19T16:39:57.000Z-08:00"
25+
}
26+
""".data(using: .utf8)!
27+
28+
let fixture = try JSONDecoder().decode(Fixture.self, from: jsonData)
29+
XCTAssertEqual(fixture.iso8601Short, Date(timeIntervalSince1970: 851013597.0))
30+
XCTAssertEqual(fixture.iso8601, Date(timeIntervalSince1970: 851013597.123))
31+
}
32+
1533
func testDecodingAndEncodingRFC3339DateString() throws {
1634
struct Fixture: Codable {
1735
@DateValue<RFC3339Strategy> var rfc3339Date: Date

0 commit comments

Comments
 (0)