Repository: diesel-rs/diesel
File: diesel/src/sqlite/types/date_and_time/chrono.rs (Rust)

Code before:
        let naive_date_time = <NaiveDateTime as FromSql<TimestampWithTz, Sqlite>>::from_sql(value)?;
        Ok(DateTime::from_utc(naive_date_time, Utc))
    }
}

impl FromSql<TimestampWithTz, Sqlite> for DateTime<Local> {
    fn from_sql(value: backend::RawValue<'_, Sqlite>) -> deserialize::Result<Self> {
        let naive_date_time = <NaiveDateTime as FromSql<TimestampWithTz, Sqlite>>::from_sql(value)?;
        Ok(Local::from_utc_datetime(&Local, &naive_date_time))
    }
}

impl<TZ: TimeZone> ToSql<TimestampWithTz, Sqlite> for DateTime<TZ> {
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
        out.set_value(self.naive_utc().format("%F %T%.f%:z").to_string());
        Ok(IsNull::No)
    }
}

#[cfg(test)]
mod tests {
    extern crate chrono;
    extern crate dotenvy;

    use self::chrono::{
        Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc,
    };

    use crate::dsl::{now, sql};
    use crate::prelude::*;
    use crate::select;
    use crate::sql_types::{Text, Time, Timestamp, TimestampWithTz};
    use crate::test_helpers::connection;

    sql_function!(fn datetime_with_tz(x: Text, z: Text) -> TimestampWithTz);
    sql_function!(fn datetime(x: Text) -> Timestamp);
    sql_function!(fn time(x: Text) -> Time);
    sql_function!(fn date(x: Text) -> Date);

    #[test]
    fn unix_epoch_encodes_correctly() {
        let connection = &mut connection();
        let time = NaiveDate::from_ymd(1970, 1, 1).and_hms(0, 0, 0);
        let query = select(datetime("1970-01-01 00:00:00.000000").eq(time));
        assert_eq!(Ok(true), query.get_result(connection));
    }

    #[test]
    fn unix_epoch_decodes_correctly_in_all_possible_formats() {
        let connection = &mut connection();
        let time = NaiveDate::from_ymd(1970, 1, 1).and_hms(0, 0, 0);

Review comment (suggestion):
Based on the documentation for `ToSql` I was led to believe that I should be trying to reuse an existing implementation (in this case I was attempting to reuse `ToSql<TimestampWithTz, Sqlite> for NaiveDateTime`) but I was getting the following errors I think due to differences in how exactly these parameters bind to the query engine itself (I don't really know exactly what I'm talking about but found the below code snippet interesting and will be looking it up)

https://github.com/diesel-rs/diesel/blob/7184f128a3c1435d12b32f413b14b6632e2f753c/diesel/src/serialize.rs#L165-L170

```
impl<TZ: TimeZone> ToSql<TimestampWithTz, Sqlite> for DateTime<TZ> {
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
        <ToSql<TimestampWithTz, Sqlite>>::to_sql(&self.naive_utc(), &mut out.reborrow())
    }
}

...

error[E0599]: the method `reborrow` exists for mutable reference `&mut serialize::Output<'b, '_, Sqlite>`, but its trait bounds were not satisfied
   --> diesel/src/sqlite/types/date_and_time/chrono.rs:166:78
    |
166 |         <ToSql<TimestampWithTz, Sqlite>>::to_sql(&self.naive_utc(), &mut out.reborrow())
    |                                                                              ^^^^^^^^ method cannot be called on `&mut serialize::Output<'b, '_, Sqlite>` due to unsatisfied trait bounds
    |
   ::: diesel/src/sqlite/backend.rs:10:1
    |
10  | pub struct Sqlite;
    | ------------------ doesn't satisfy `<_ as backend::private::HasBindCollector<'a>>::BindCollector = RawBytesBindCollector<Sqlite>`
    |
    = note: the following trait bounds were not satisfied:
            `<Sqlite as backend::private::HasBindCollector<'a>>::BindCollector = RawBytesBindCollector<Sqlite>`
```

Code after:
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
        out.set_value(self.format("%F %T%.f+00:00").to_string());
        Ok(IsNull::No)
    }
}

#[cfg(all(feature = "sqlite", feature = "chrono"))]
impl FromSql<TimestamptzSqlite, Sqlite> for DateTime<Utc> {
    fn from_sql(value: backend::RawValue<'_, Sqlite>) -> deserialize::Result<Self> {
        let naive_date_time =
            <NaiveDateTime as FromSql<TimestamptzSqlite, Sqlite>>::from_sql(value)?;
        Ok(DateTime::from_utc(naive_date_time, Utc))
    }
}

#[cfg(all(feature = "sqlite", feature = "chrono"))]
impl FromSql<TimestamptzSqlite, Sqlite> for DateTime<Local> {
    fn from_sql(value: backend::RawValue<'_, Sqlite>) -> deserialize::Result<Self> {
        let naive_date_time =
            <NaiveDateTime as FromSql<TimestamptzSqlite, Sqlite>>::from_sql(value)?;
        Ok(Local::from_utc_datetime(&Local, &naive_date_time))
    }
}

#[cfg(all(feature = "sqlite", feature = "chrono"))]
impl<TZ: TimeZone> ToSql<TimestamptzSqlite, Sqlite> for DateTime<TZ> {
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
        out.set_value(self.naive_utc().format("%F %T%.f+00:00").to_string());
        Ok(IsNull::No)
    }
}

#[cfg(test)]
mod tests {
    extern crate chrono;
    extern crate dotenvy;

    use self::chrono::{
        DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Timelike,
        Utc,
    };

    use crate::dsl::{now, sql};
    use crate::prelude::*;
    use crate::select;
    use crate::sql_types::{Text, Time, Timestamp, TimestamptzSqlite};
    use crate::test_helpers::connection;

    sql_function!(fn datetime(x: Text) -> Timestamp);
    sql_function!(fn time(x: Text) -> Time);
    sql_function!(fn date(x: Text) -> Date);