Skip to content

Commit

Permalink
Added example of MultiDateFormat to README and cleaned up MultiDateFo…
Browse files Browse the repository at this point in the history
…rmat tests a bit
  • Loading branch information
pendikov committed May 27, 2019
1 parent 7e23305 commit 9f91a4f
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 107 deletions.
4 changes: 2 additions & 2 deletions MoreCodable.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@
24028DD1204859A400721297 /* ObjectMergerTests.swift */,
24CF7FE52144DCA4007A5C6C /* CodableDictionaryTests.swift */,
24CF7FE92144E7DC007A5C6C /* CodableAnyTests.swift */,
24A4FF4020302322001618E1 /* Products */,
24A4FF5820302490001618E1 /* Info.plist */,
C47ABFCC22991B09005A06B5 /* MoreJSONEncoderTests.swift */,
C47ABFCE22992041005A06B5 /* MoreJSONDecoderTests.swift */,
24A4FF4020302322001618E1 /* Products */,
24A4FF5820302490001618E1 /* Info.plist */,
);
path = Tests;
sourceTree = "<group>";
Expand Down
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,60 @@ XCTAssertEqual(root.int.value, 100)
XCTAssertEqual(root.articleId.value.description, "abc")
```

## MultiDateFormat
```swift
let json = """
{
"date": "2019.05.27",
"dateTime": "2019-05-27T17:26:59+0000",
"timestamp": 1558978068,
"timestampMilliseconds": 1558978141863,
"custom": "1558978068"
}
""".data(using: .utf8)!

struct Document: Codable {
var date: Date
var dateTime: Date
var timestamp: Date
var timestampMilliseconds: Date
var custom: Date
}

extension Document: MultiDateFormat {

static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy.MM.dd"
return formatter
}()

static func dateFormat(for codingKey: CodingKey) -> DateFormat? {
switch codingKey {
case CodingKeys.date: return .formatted(dateFormatter)
case CodingKeys.dateTime: return .iso8601
case CodingKeys.timestamp: return .secondsSince1970
case CodingKeys.timestampMilliseconds: return .millisecondsSince1970
case CodingKeys.custom: return .custom({ (date, encoder) in
var container = encoder.singleValueContainer()
try container.encode(String(date.timeIntervalSince1970))
}, { (decoder) -> Date in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let timeInterval = TimeInterval(string)!
return Date(timeIntervalSince1970: timeInterval)
})
default: return nil
}
}

}

let decoded = try! MoreJSONDecoder().decode(Document.self, from: json)
let encoded = try! MoreJSONEncoder().encode(document)
```

# ToDo
- [ ] XMLDecoder/XMLEncoder
- [ ] CSVDecoder/CSVEncoder
Expand Down
2 changes: 1 addition & 1 deletion Sources/MultiDateFormat.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// MultiDateFormat.swift
// MultiDateFormat
// MoreCodable
//
// Created by Daniil Pendikov on 24/05/2019.
// Copyright © 2019 tattn. All rights reserved.
Expand Down
112 changes: 61 additions & 51 deletions Tests/MoreJSONDecoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,61 @@
import XCTest
@testable import MoreCodable

class MoreJSONDecoderTests: XCTestCase {

var decoder = MoreJSONDecoder()
fileprivate struct Document: Codable {
var date: Date
var dateTime: Date
var timestamp: Date
var timestampMilliseconds: Date
var custom: Date
}

struct User: Codable {
let name: String
let age: Int
}
extension Document: MultiDateFormat {

static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy.MM.dd"
return formatter
}()

override func setUp() {
decoder = MoreJSONDecoder()
static func dateFormat(for codingKey: CodingKey) -> DateFormat? {
switch codingKey {
case CodingKeys.date: return .formatted(dateFormatter)
case CodingKeys.dateTime: return .iso8601
case CodingKeys.timestamp: return .secondsSince1970
case CodingKeys.timestampMilliseconds: return .millisecondsSince1970
case CodingKeys.custom: return .custom({ (date, encoder) in
var container = encoder.singleValueContainer()
try container.encode(String(date.timeIntervalSince1970))
}, { (decoder) -> Date in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let timeInterval = TimeInterval(string)!
return Date(timeIntervalSince1970: timeInterval)
})
default: return nil
}
}

}

fileprivate let json = """
{
"date": "2019.05.27",
"dateTime": "2019-05-27T17:26:59+0000",
"timestamp": 1558978068,
"timestampMilliseconds": 1558978141863,
"custom": "1558978068"
}
"""

class MoreJSONDecoderTests: XCTestCase {

func testDecodeSimpleModel() throws {
struct User: Codable {
let name: String
let age: Int
}
let user = User(name: "Tatsuya Tanaka", age: 24)
let data = try MoreJSONEncoder().encode(user)
XCTAssertGreaterThan(data.count, 0)
Expand All @@ -32,49 +73,18 @@ class MoreJSONDecoderTests: XCTestCase {
}

func testSimpleMultiDateFormat() throws {
struct Doc: Codable, MultiDateFormat {

static var dateFormatter1: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy-MM-dd-HH-mm"
return formatter
}()

static var dateFormatter2: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy.MM.dd.HH.mm"
return formatter
}()

var id: String
var date1: Date
var date2: Date

static func dateFormat(for codingKey: CodingKey) -> DateFormat? {
switch codingKey {
case CodingKeys.date1: return .formatted(dateFormatter1)
case CodingKeys.date2: return .formatted(dateFormatter2)
default: return nil
}
}

let data = json.data(using: .utf8)!
let document = try MoreJSONDecoder().decode(Document.self, from: data)
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "UTC")!
let dates = [document.date, document.dateTime, document.timestamp, document.timestampMilliseconds, document.custom]

for date in dates {
let components = calendar.dateComponents([.year, .month, .day], from: date)
XCTAssertEqual(components.year, 2019)
XCTAssertEqual(components.month, 5)
XCTAssertEqual(components.day, 27)
}
let numSecondsInYear: TimeInterval = 365 * 24 * 60 * 60
let doc = Doc(id: "1", date1: Date(timeIntervalSince1970: 0),
date2: Date(timeIntervalSince1970: numSecondsInYear * 1.5))
let data = try MoreJSONEncoder().encode(doc)
XCTAssertGreaterThan(data.count, 0)
let decoded = try MoreJSONDecoder().decode(Doc.self, from: data)
XCTAssertGreaterThan(data.count, 0)
XCTAssertEqual(decoded.id, doc.id)
XCTAssertEqual(decoded.date1, doc.date1)
XCTAssertEqual(decoded.date2, doc.date2)
}

override func tearDown() {
super.tearDown()
}

}
114 changes: 61 additions & 53 deletions Tests/MoreJSONEncoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,53 @@
import XCTest
@testable import MoreCodable

class MoreJSONEncoderTests: XCTestCase {
fileprivate struct Document: Codable {
var date: Date
var dateTime: Date
var timestamp: Date
var timestampMilliseconds: Date
var custom: Date
}

extension Document: MultiDateFormat {

static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy.MM.dd"
return formatter
}()

struct User: Codable {
let name: String
let age: Int
static func dateFormat(for codingKey: CodingKey) -> DateFormat? {
switch codingKey {
case CodingKeys.date: return .formatted(dateFormatter)
case CodingKeys.dateTime: return .iso8601
case CodingKeys.timestamp: return .secondsSince1970
case CodingKeys.timestampMilliseconds: return .millisecondsSince1970
case CodingKeys.custom: return .custom({ (date, encoder) in
var container = encoder.singleValueContainer()
try container.encode(String(date.timeIntervalSince1970))
}, { (decoder) -> Date in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let timeInterval = TimeInterval(string)!
return Date(timeIntervalSince1970: timeInterval)
})
default: return nil
}
}

var encoder = MoreJSONEncoder()
}

override func setUp() {
encoder = MoreJSONEncoder()
}
class MoreJSONEncoderTests: XCTestCase {

func testDecodeSimpleModel() throws {
func testEncodeSimpleModel() throws {
struct User: Codable {
let name: String
let age: Int
}
let user = User(name: "Tatsuya Tanaka", age: 24)
let data = try encoder.encode(user)
let data = try MoreJSONEncoder().encode(user)
XCTAssertGreaterThan(data.count, 0)
let dic = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
XCTAssertEqual(user.name, dic["name"] as? String)
Expand All @@ -33,49 +64,26 @@ class MoreJSONEncoderTests: XCTestCase {
}

func testSimpleMultiDateFormat() throws {
struct Doc: Codable, MultiDateFormat {

static var dateFormatter1: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy-MM-dd-HH-mm"
return formatter
}()

static var dateFormatter2: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy.MM.dd.HH.mm"
return formatter
}()

var id: String
var date1: Date
var date2: Date

static func dateFormat(for codingKey: CodingKey) -> DateFormat? {
switch codingKey {
case CodingKeys.date1: return .formatted(dateFormatter1)
case CodingKeys.date2: return .formatted(dateFormatter2)
default: return nil
}
}

}
let numSecondsInYear: TimeInterval = 365 * 24 * 60 * 60
let doc = Doc(id: "1", date1: Date(timeIntervalSince1970: 0),
date2: Date(timeIntervalSince1970: numSecondsInYear * 1.5))
let data = try encoder.encode(doc)
XCTAssertGreaterThan(data.count, 0)
let date = Date(timeIntervalSince1970: 0)
let document = Document(date: date, dateTime: date, timestamp: date, timestampMilliseconds: date, custom: date)
let data = try MoreJSONEncoder().encode(document)
let dic = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
XCTAssertGreaterThan(data.count, 0)
XCTAssertEqual(dic["id"] as? String, doc.id)
XCTAssertEqual((dic["date1"] as? String)?.contains("1970"), true)
XCTAssertEqual((dic["date2"] as? String)?.contains("1971"), true)
}

override func tearDown() {
super.tearDown()

XCTAssertTrue(dic["date"] is String)
XCTAssertTrue(dic["dateTime"] is String)
XCTAssertTrue(dic["timestamp"] is Double)
XCTAssertTrue(dic["timestampMilliseconds"] is Double)
XCTAssertTrue(dic["custom"] is String)

var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "UTC")!
let decoded = try! MoreJSONDecoder().decode(Document.self, from: data)
for date in [decoded.date, decoded.dateTime, decoded.timestamp, decoded.timestampMilliseconds, decoded.custom] {
let components = calendar.dateComponents([.year, .month, .day], from: date)
XCTAssertEqual(components.year, 1970)
XCTAssertEqual(components.month, 1)
XCTAssertEqual(components.day, 1)
}

}

}

0 comments on commit 9f91a4f

Please sign in to comment.