mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-02 15:25:32 +00:00
Sqlite support for DateTime<{Utc,Local}>.
This commit is contained in:
parent
4254735dcf
commit
516af07713
@ -22,40 +22,67 @@ 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 {
|
||||
// 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 = &[
|
||||
// Most likely format
|
||||
"%F %T%.f",
|
||||
// Other formats in order of appearance in docs
|
||||
"%F %R",
|
||||
"%F %RZ",
|
||||
"%F %R%:z",
|
||||
"%F %T%.fZ",
|
||||
"%F %T%.f%:z",
|
||||
"%FT%R",
|
||||
"%FT%RZ",
|
||||
"%FT%R%:z",
|
||||
"%FT%T%.f",
|
||||
"%FT%T%.fZ",
|
||||
"%FT%T%.f%:z",
|
||||
];
|
||||
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 = &[
|
||||
// Most likely format
|
||||
"%F %T%.f",
|
||||
// Other formats in order of appearance in docs
|
||||
"%F %R",
|
||||
"%F %RZ",
|
||||
"%F %R%:z",
|
||||
"%F %T%.fZ",
|
||||
"%F %T%.f%:z",
|
||||
"%FT%R",
|
||||
"%FT%RZ",
|
||||
"%FT%R%:z",
|
||||
"%FT%T%.f",
|
||||
"%FT%T%.fZ",
|
||||
"%FT%T%.f%:z",
|
||||
];
|
||||
|
||||
for format in sqlite_datetime_formats {
|
||||
if let Ok(dt) = NaiveDateTime::parse_from_str(raw, format) {
|
||||
return Ok(dt);
|
||||
}
|
||||
for format in sqlite_datetime_formats {
|
||||
if let Ok(dt) = NaiveDateTime::parse_from_str(text, format) {
|
||||
return Ok(dt);
|
||||
}
|
||||
|
||||
return Err(err_protocol!("Did not find a matching pattern").into());
|
||||
}
|
||||
|
||||
Err(err_protocol!("There was no text value to decode").into())
|
||||
return Err(err_protocol!("Did not find a matching pattern").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))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user