Sqlite support for DateTime<{Utc,Local}>.

This commit is contained in:
Felipe Lessa 2020-06-27 09:31:42 +01:00
parent 4254735dcf
commit 516af07713
No known key found for this signature in database
GPG Key ID: 210DC649890C2FEA

View File

@ -22,13 +22,11 @@ impl Encode<'_, Sqlite> for NaiveDateTime {
impl<'a> Decode<'a, Sqlite> for NaiveDateTime {
fn decode(value: SqliteValueRef<'a>) -> Result<Self, BoxDynError> {
let text = Decode::<Sqlite>::decode(value)?;
decode_from_text(text)
decode_naive_from_text(value.text()?)
}
}
fn decode_from_text(text: Option<&str>) -> Result<NaiveDateTime, BoxDynError> {
if let Some(raw) = text {
fn decode_naive_from_text(text: &str) -> Result<NaiveDateTime, BoxDynError> {
// Loop over common date time patterns, inspired by Diesel
// https://docs.diesel.rs/src/diesel/sqlite/types/date_and_time/chrono.rs.html#56-97
let sqlite_datetime_formats = &[
@ -49,7 +47,7 @@ fn decode_from_text(text: Option<&str>) -> Result<NaiveDateTime, BoxDynError> {
];
for format in sqlite_datetime_formats {
if let Ok(dt) = NaiveDateTime::parse_from_str(raw, format) {
if let Ok(dt) = NaiveDateTime::parse_from_str(text, format) {
return Ok(dt);
}
}
@ -57,5 +55,34 @@ fn decode_from_text(text: Option<&str>) -> Result<NaiveDateTime, BoxDynError> {
return Err(err_protocol!("Did not find a matching pattern").into());
}
Err(err_protocol!("There was no text value to decode").into())
impl<Tz: TimeZone> Type<Sqlite> for DateTime<Tz> {
fn type_info() -> SqliteTypeInfo {
SqliteTypeInfo(DataType::Timestamp)
}
}
impl<Tz: TimeZone> Encode<'_, Sqlite> for DateTime<Tz> {
fn encode_by_ref(&self, buf: &mut Vec<SqliteArgumentValue<'_>>) -> IsNull {
let text = self.with_timezone(&Utc).to_rfc3339();
Encode::<Sqlite>::encode(text, buf)
}
}
impl<'a> Decode<'a, Sqlite> for DateTime<Utc> {
fn decode(value: SqliteValueRef<'a>) -> Result<Self, BoxDynError> {
let text = value.text()?;
if let Ok(dt) = DateTime::parse_from_rfc3339(text) {
Ok(dt.with_timezone(&Utc))
} else {
let dt = decode_naive_from_text(text)?;
Ok(Utc.from_utc_datetime(&dt))
}
}
}
impl<'a> Decode<'a, Sqlite> for DateTime<Local> {
fn decode(value: SqliteValueRef<'a>) -> Result<Self, BoxDynError> {
let as_utc: DateTime<Utc> = Decode::<Sqlite>::decode(value)?;
Ok(as_utc.with_timezone(&Local))
}
}