Skip to content

Commit 9b0e41a

Browse files
committed
Details about date formats
1 parent d40474d commit 9b0e41a

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

README.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,8 @@ Here is how GRDB supports the various [date formats](https://www.sqlite.org/lang
13881388

13891389
³ GRDB 2+ interprets numerical values as timestamps that fuel `Date(timeIntervalSince1970:)`. Previous GRDB versions used to interpret numbers as [julian days](https://en.wikipedia.org/wiki/Julian_day). Julian days are still supported, with the `Date(julianDay:)` initializer.
13901390

1391+
> :warning: **Warning**: the range of valid years in the SQLite date formats is 0000-9999. You will need to pick another date format when your application needs to process years outside of this range. See the following chapters.
1392+
13911393

13921394
#### Date
13931395

@@ -1410,19 +1412,39 @@ Dates are stored using the format "YYYY-MM-DD HH:MM:SS.SSS" in the UTC time zone
14101412
> - Comparable with the SQLite keyword CURRENT_TIMESTAMP (`WHERE date > CURRENT_TIMESTAMP` works)
14111413
> - Able to feed [SQLite date & time functions](https://www.sqlite.org/lang_datefunc.html)
14121414
> - Precise enough
1415+
>
1416+
> :warning: **Warning**: the range of valid years in the SQLite date format is 0000-9999. You will experience problems with years outside of this range, such as decoding errors, or invalid date computations with [SQLite date & time functions](https://www.sqlite.org/lang_datefunc.html).
1417+
1418+
Some applications may prefer another date format:
1419+
1420+
- Some may prefer ISO-8601, with a `T` separator.
1421+
- Some may prefer ISO-8601, with a time zone.
1422+
- Some may need to store years beyond the 0000-9999 range.
1423+
- Some may need sub-millisecond precision.
1424+
- Some may need exact `Date` roundtrip.
1425+
- Etc.
1426+
1427+
**You should think twice before choosing a different date format:**
14131428

1414-
When the default format does not fit your needs, customize date conversions. For example:
1429+
- ISO-8601 is about *exchange and communication*, when SQLite is about *storage and data manipulation*. Sharing the same representation in your database and in JSON files only provides a superficial convenience, and should be the least of your priorities. Don't store dates as ISO-8601 without understanding what you lose. For example, ISO-8601 time zones forbid database-level date comparison.
1430+
- Sub-millisecond precision and exact `Date` roundtrip are not as obvious needs as it seems at first sight. Dates generally don't precisely roundtrip as soon as they leave your application anyway, because the other systems your app communicates with use their own date representation (the Android version of your app, the server your application is talking to, etc.) On top of that, `Date` comparison is at least as hard and nasty as [floating point comparison](https://www.google.com/search?q=floating+point+comparison+is+hard).
1431+
1432+
The customization of date format is explicit. For example:
14151433

14161434
```swift
1435+
let date = Date()
1436+
let timeInterval = date.timeIntervalSinceReferenceDate
14171437
try db.execute(
14181438
sql: "INSERT INTO player (creationDate, ...) VALUES (?, ...)",
1419-
arguments: [Date().timeIntervalSinceReferenceDate, ...])
1439+
arguments: [timeInterval, ...])
14201440

1421-
let row = try Row.fetchOne(db, ...)!
1422-
let creationDate = Date(timeIntervalSinceReferenceDate: row["creationDate"])
1441+
if let row = try Row.fetchOne(db, ...) {
1442+
let timeInterval: TimeInterval = row["creationDate"]
1443+
let creationDate = Date(timeIntervalSinceReferenceDate: timeInterval)
1444+
}
14231445
```
14241446

1425-
See [Codable Records] for more date customization options.
1447+
See also [Codable Records] for more date customization options, and [DatabaseValueConvertible](#custom-value-types) if you want to define a Date-wrapping type with customized database representation.
14261448

14271449

14281450
#### DateComponents
@@ -1431,6 +1453,8 @@ DateComponents is indirectly supported, through the **DatabaseDateComponents** h
14311453

14321454
DatabaseDateComponents reads date components from all [date formats supported by SQLite](https://www.sqlite.org/lang_datefunc.html), and stores them in the format of your choice, from HH:MM to YYYY-MM-DD HH:MM:SS.SSS.
14331455

1456+
> :warning: **Warning**: the range of valid years is 0000-9999. You will experience problems with years outside of this range, such as decoding errors, or invalid date computations with [SQLite date & time functions](https://www.sqlite.org/lang_datefunc.html). See [Date](#date) for more information.
1457+
14341458
DatabaseDateComponents can be stored and fetched from the database just like other [values](#values):
14351459

14361460
```swift

0 commit comments

Comments
 (0)