Skip to content

Commit 67a7f8a

Browse files
committed
Add Codable Date Support
1 parent ed8f603 commit 67a7f8a

File tree

4 files changed

+27
-14
lines changed

4 files changed

+27
-14
lines changed

Documentation/Index.md

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1557,7 +1557,7 @@ Both of the above methods also have the following optional parameter:
15571557
There are a few restrictions on using Codable types:
15581558

15591559
- The encodable and decodable objects can only use the following types:
1560-
- Int, Bool, Float, Double, String
1560+
- Int, Bool, Float, Double, String, Date
15611561
- Nested Codable types that will be encoded as JSON to a single column
15621562
- These methods will not handle object relationships for you. You must write
15631563
your own Codable and Decodable implementations if you wish to support this.

Sources/SQLite/Typed/Coding.swift

100644100755
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ fileprivate class SQLiteEncoder: Encoder {
132132
if let data = value as? Data {
133133
self.encoder.setters.append(Expression(key.stringValue) <- data)
134134
}
135+
else if let date = value as? Date {
136+
self.encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
137+
}
135138
else {
136139
let encoded = try JSONEncoder().encode(value)
137140
let string = String(data: encoded, encoding: .utf8)
@@ -290,6 +293,10 @@ fileprivate class SQLiteDecoder : Decoder {
290293
let data = try self.row.get(Expression<Data>(key.stringValue))
291294
return data as! T
292295
}
296+
else if type == Date.self {
297+
let date = try self.row.get(Expression<Date>(key.stringValue))
298+
return date as! T
299+
}
293300
guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
294301
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "an unsupported type was found"))
295302
}

Tests/SQLiteTests/QueryTests.swift

100644100755
Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,23 +249,23 @@ class QueryTests : XCTestCase {
249249

250250
func test_insert_encodable() throws {
251251
let emails = Table("emails")
252-
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
252+
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
253253
let insert = try emails.insert(value)
254254
AssertSQL(
255-
"INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0)",
255+
"INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000')",
256256
insert
257257
)
258258
}
259259

260260
func test_insert_encodable_with_nested_encodable() throws {
261261
let emails = Table("emails")
262-
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
263-
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: "optional", sub: value1)
262+
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
263+
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: "optional", sub: value1)
264264
let insert = try emails.insert(value)
265265
let encodedJSON = try JSONEncoder().encode(value1)
266266
let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
267267
AssertSQL(
268-
"INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', '\(encodedJSONString)')",
268+
"INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'optional', '\(encodedJSONString)')",
269269
insert
270270
)
271271
}
@@ -286,23 +286,23 @@ class QueryTests : XCTestCase {
286286

287287
func test_update_encodable() throws {
288288
let emails = Table("emails")
289-
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
289+
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
290290
let update = try emails.update(value)
291291
AssertSQL(
292-
"UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0",
292+
"UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000'",
293293
update
294294
)
295295
}
296296

297297
func test_update_encodable_with_nested_encodable() throws {
298298
let emails = Table("emails")
299-
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
300-
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: value1)
299+
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
300+
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
301301
let update = try emails.update(value)
302302
let encodedJSON = try JSONEncoder().encode(value1)
303303
let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
304304
AssertSQL(
305-
"UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = '\(encodedJSONString)'",
305+
"UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'",
306306
update
307307
)
308308
}
@@ -438,12 +438,13 @@ class QueryIntegrationTests : SQLiteTestCase {
438438
builder.column(Expression<Bool>("bool"))
439439
builder.column(Expression<Double>("float"))
440440
builder.column(Expression<Double>("double"))
441+
builder.column(Expression<Date>("date"))
441442
builder.column(Expression<String?>("optional"))
442443
builder.column(Expression<Data>("sub"))
443444
})
444445

445-
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
446-
let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, optional: "optional", sub: value1)
446+
let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
447+
let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
447448

448449
try db.run(table.insert(value))
449450

@@ -455,12 +456,14 @@ class QueryIntegrationTests : SQLiteTestCase {
455456
XCTAssertEqual(values[0].bool, true)
456457
XCTAssertEqual(values[0].float, 7)
457458
XCTAssertEqual(values[0].double, 8)
459+
XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
458460
XCTAssertEqual(values[0].optional, "optional")
459461
XCTAssertEqual(values[0].sub?.int, 1)
460462
XCTAssertEqual(values[0].sub?.string, "2")
461463
XCTAssertEqual(values[0].sub?.bool, true)
462464
XCTAssertEqual(values[0].sub?.float, 3)
463465
XCTAssertEqual(values[0].sub?.double, 4)
466+
XCTAssertEqual(values[0].sub?.date, Date(timeIntervalSince1970: 0))
464467
XCTAssertNil(values[0].sub?.optional)
465468
XCTAssertNil(values[0].sub?.sub)
466469
}

Tests/SQLiteTests/TestHelpers.swift

100644100755
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class SQLiteTestCase : XCTestCase {
2626
salary REAL,
2727
admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
2828
manager_id INTEGER,
29+
created_at DATETIME,
2930
FOREIGN KEY(manager_id) REFERENCES users(id)
3031
)
3132
"""
@@ -111,15 +112,17 @@ class TestCodable: Codable {
111112
let bool: Bool
112113
let float: Float
113114
let double: Double
115+
let date: Date
114116
let optional: String?
115117
let sub: TestCodable?
116118

117-
init(int: Int, string: String, bool: Bool, float: Float, double: Double, optional: String?, sub: TestCodable?) {
119+
init(int: Int, string: String, bool: Bool, float: Float, double: Double, date: Date, optional: String?, sub: TestCodable?) {
118120
self.int = int
119121
self.string = string
120122
self.bool = bool
121123
self.float = float
122124
self.double = double
125+
self.date = date
123126
self.optional = optional
124127
self.sub = sub
125128
}

0 commit comments

Comments
 (0)