preserve offset when writing chrono::DateTime<FixedOffset>

This commit is contained in:
Lukas Himbert 2021-11-14 15:31:58 +01:00 committed by Thom Chiovoloni
parent 0960e75fd2
commit 53e74a3f09

View File

@ -1,6 +1,6 @@
//! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types. //! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types.
use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc}; use chrono::{DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef}; use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
use crate::Result; use crate::Result;
@ -83,9 +83,19 @@ impl FromSql for NaiveDateTime {
} }
} }
/// Date and time with time zone => UTC RFC3339 timestamp /// UTC time => UTC RFC3339 timestamp
/// ("YYYY-MM-DD HH:MM:SS.SSS+00:00"). /// ("YYYY-MM-DD HH:MM:SS.SSS+00:00").
impl<Tz: TimeZone> ToSql for DateTime<Tz> { impl ToSql for DateTime<Utc> {
#[inline]
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
let date_str = self.format("%F %T%.f%:z").to_string();
Ok(ToSqlOutput::from(date_str))
}
}
/// Local time => UTC RFC3339 timestamp
/// ("YYYY-MM-DD HH:MM:SS.SSS+00:00").
impl ToSql for DateTime<Local> {
#[inline] #[inline]
fn to_sql(&self) -> Result<ToSqlOutput<'_>> { fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
let date_str = self.with_timezone(&Utc).format("%F %T%.f%:z").to_string(); let date_str = self.with_timezone(&Utc).format("%F %T%.f%:z").to_string();
@ -93,6 +103,16 @@ impl<Tz: TimeZone> ToSql for DateTime<Tz> {
} }
} }
/// Date and time with time zone => RFC3339 timestamp
/// ("YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM").
impl ToSql for DateTime<FixedOffset> {
#[inline]
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
let date_str = self.format("%F %T%.f%:z").to_string();
Ok(ToSqlOutput::from(date_str))
}
}
/// RFC3339 ("YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM") into `DateTime<Utc>`. /// RFC3339 ("YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM") into `DateTime<Utc>`.
impl FromSql for DateTime<Utc> { impl FromSql for DateTime<Utc> {
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> { fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
@ -233,6 +253,22 @@ mod test {
Ok(()) Ok(())
} }
#[test]
fn test_date_time_fixed() -> Result<()> {
let db = checked_memory_handle()?;
let time = DateTime::parse_from_rfc3339("2020-04-07T11:23:45+04:00").unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", [time])?;
// Stored string should preserve timezone offset
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
assert!(s.ends_with("+04:00"));
let v: DateTime<Local> = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
assert_eq!(time, v);
Ok(())
}
#[test] #[test]
fn test_sqlite_functions() -> Result<()> { fn test_sqlite_functions() -> Result<()> {
let db = checked_memory_handle()?; let db = checked_memory_handle()?;