Sqlite support for DateTime<{Utc,Local}>.
@@ -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))
+ }
}
