mirror of
https://github.com/isar/rusqlite.git
synced 2025-09-16 20:52:19 +08:00
Fix date/time format for SQLite, use RFC 3339
We implement `ToSql` and `FromSql` for `time::Timespec` values. Our documentation indicates that we store the value in the same format used by SQLite's built-in date/time functions, but this was not correct. We were using the format: %Y-%m-%d %H:%M:%S:%f %Z This format cannot be interpreted at all by SQLite's built-in date/time functions. There are three reasons for this: - SQLite supports only two timezone formats: `[+-]HH:MM` and the literal character `Z` (indicating UTC) - SQLite does not support a space before the timezone indicator - SQLite supports a period (`.`) between the seconds field and the fractional seconds field, but not a colon (`:`) SQLite does support the RFC 3339 date/time format, which is standard in many other places. As we're always storing a UTC value, we'll simply use a trailing `Z` to indicate the timezone, as allowed by RFC 3339. The new format is: %Y-%m-%dT%H:%M:%S.%fZ To avoid breaking applications using databases with values in the old format, we'll continue to support it as a fallback for `FromSql`. [1] https://www.sqlite.org/lang_datefunc.html [2] https://tools.ietf.org/html/rfc3339
This commit is contained in:
@@ -3,7 +3,8 @@ extern crate time;
|
||||
use Result;
|
||||
use types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
|
||||
|
||||
const SQLITE_DATETIME_FMT: &str = "%Y-%m-%d %H:%M:%S:%f %Z";
|
||||
const SQLITE_DATETIME_FMT: &str = "%Y-%m-%dT%H:%M:%S.%fZ";
|
||||
const SQLITE_DATETIME_FMT_LEGACY: &str = "%Y-%m-%d %H:%M:%S:%f %Z";
|
||||
|
||||
impl ToSql for time::Timespec {
|
||||
fn to_sql(&self) -> Result<ToSqlOutput> {
|
||||
@@ -19,10 +20,12 @@ impl FromSql for time::Timespec {
|
||||
fn column_result(value: ValueRef) -> FromSqlResult<Self> {
|
||||
value
|
||||
.as_str()
|
||||
.and_then(|s| match time::strptime(s, SQLITE_DATETIME_FMT) {
|
||||
Ok(tm) => Ok(tm.to_timespec()),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
})
|
||||
.and_then(|s| {
|
||||
time::strptime(s, SQLITE_DATETIME_FMT)
|
||||
.or_else(|err| {
|
||||
time::strptime(s, SQLITE_DATETIME_FMT_LEGACY)
|
||||
.or(Err(FromSqlError::Other(Box::new(err))))})})
|
||||
.map(|tm| tm.to_timespec())
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user