#![cfg(any(feature = "rusqlite", feature = "turso", feature = "libsql"))]
#[cfg(feature = "jiff")]
mod jiff_values {
use drizzle::core::expr::*;
use drizzle::sqlite::prelude::*;
use jiff::Timestamp;
use jiff::civil::{Date, DateTime, Time};
#[SQLiteTable(NAME = "jiff_events")]
struct JiffEvent {
#[column(PRIMARY)]
id: i32,
day: Date,
starts: Time,
local: DateTime,
instant: Timestamp,
ends: Option<Timestamp>,
}
#[derive(SQLiteSchema)]
struct JiffSchema {
events: JiffEvent,
}
#[drizzle::test]
fn jiff_values_round_trip(db: &mut TestDb<JiffSchema>) {
let JiffSchema { events } = schema;
let day = jiff::civil::date(2026, 9, 23);
let starts = jiff::civil::time(9, 30, 15, 500_000_000);
let local = day.at(9, 30, 15, 0);
let instant: Timestamp = "2026-09-23T07:30:15Z".parse().unwrap();
db.insert(events)
.values([InsertJiffEvent::new(day, starts, local, instant).with_id(1)])
.execute();
let row: SelectJiffEvent = db.select(()).from(events).get();
assert_eq!(
(row.day, row.starts, row.local, row.instant, row.ends),
(day, starts, local, instant, None)
);
let (selected_day, selected_local, selected_instant): (Date, DateTime, Timestamp) = db
.select((events.day, events.local, events.instant))
.from(events)
.get();
assert_eq!(
(selected_day, selected_local, selected_instant),
(day, local, instant)
);
let matched: Vec<SelectJiffEvent> = db
.select(())
.from(events)
.r#where(and(eq(events.local, local), eq(events.instant, instant)))
.all();
assert_eq!(matched.len(), 1);
}
#[drizzle::test]
fn jiff_values_read_sqlite_datetime_text(db: &mut TestDb<JiffSchema>) {
let JiffSchema { events } = schema;
result!(db.execute(SQL::raw(
r#"INSERT INTO "jiff_events" ("id", "day", "starts", "local", "instant")
VALUES (1, '2026-09-23', '09:30:15', '2026-09-23 09:30:15', '2026-09-23 07:30:15')"#
)))?;
let row: SelectJiffEvent = db.select(()).from(events).get();
assert_eq!(row.local, jiff::civil::date(2026, 9, 23).at(9, 30, 15, 0));
assert_eq!(
row.instant,
"2026-09-23T07:30:15Z".parse::<Timestamp>().unwrap()
);
}
}
#[cfg(feature = "time")]
mod time_values {
use drizzle::sqlite::prelude::*;
use time::macros::{date, datetime, time};
#[SQLiteTable(NAME = "time_events")]
struct TimeEvent {
#[column(PRIMARY)]
id: i32,
day: time::Date,
starts: time::Time,
local: time::PrimitiveDateTime,
instant: time::OffsetDateTime,
}
#[derive(SQLiteSchema)]
struct TimeSchema {
events: TimeEvent,
}
#[drizzle::test]
fn time_values_decode_in_models_and_selected_columns(db: &mut TestDb<TimeSchema>) {
let TimeSchema { events } = schema;
let day = date!(2026 - 09 - 23);
let starts = time!(9:30:15.5);
let local = datetime!(2026-09-23 9:30:15);
let instant = datetime!(2026-09-23 7:30:15 UTC);
db.insert(events)
.values([InsertTimeEvent::new(day, starts, local, instant).with_id(1)])
.execute();
let row: SelectTimeEvent = db.select(()).from(events).get();
assert_eq!(
(row.day, row.starts, row.local, row.instant),
(day, starts, local, instant)
);
let (selected_day, selected_local, selected_instant): (
time::Date,
time::PrimitiveDateTime,
time::OffsetDateTime,
) = db
.select((events.day, events.local, events.instant))
.from(events)
.get();
assert_eq!(
(selected_day, selected_local, selected_instant),
(day, local, instant)
);
}
#[drizzle::test]
fn time_values_read_sqlite_datetime_text(db: &mut TestDb<TimeSchema>) {
let TimeSchema { events } = schema;
result!(db.execute(SQL::raw(
r#"INSERT INTO "time_events" ("id", "day", "starts", "local", "instant")
VALUES (1, '2026-09-23', 'T09:30:15.500000000', '2026-09-23 09:30:15', '2026-09-23 07:30:15')"#
)))?;
let row: SelectTimeEvent = db.select(()).from(events).get();
assert_eq!(
(row.starts, row.local, row.instant),
(
time!(9:30:15.5),
datetime!(2026-09-23 9:30:15),
datetime!(2026-09-23 7:30:15 UTC)
)
);
}
#[drizzle::test]
fn time_values_compare_in_filters(db: &mut TestDb<TimeSchema>) {
let TimeSchema { events } = schema;
let day = date!(2026 - 09 - 23);
let instant = datetime!(2026-09-23 7:30:15 UTC);
db.insert(events)
.values([
InsertTimeEvent::new(day, time!(9:30), datetime!(2026-09-23 9:30), instant)
.with_id(1),
])
.execute();
let matched: Vec<SelectTimeEvent> = db
.select(())
.from(events)
.r#where(drizzle::core::expr::and(
drizzle::core::expr::eq(events.day, day),
drizzle::core::expr::eq(events.instant, instant),
))
.all();
assert_eq!(matched.len(), 1);
}
}
#[cfg(feature = "chrono")]
mod chrono_values {
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
use drizzle::core::expr::*;
use drizzle::sqlite::prelude::*;
#[SQLiteTable(NAME = "chrono_events")]
struct ChronoEvent {
#[column(PRIMARY)]
id: i32,
day: NaiveDate,
starts: NaiveTime,
local: NaiveDateTime,
zoned: DateTime<FixedOffset>,
instant: DateTime<Utc>,
}
#[derive(SQLiteSchema)]
struct ChronoSchema {
events: ChronoEvent,
}
fn values() -> (
NaiveDate,
NaiveTime,
NaiveDateTime,
DateTime<FixedOffset>,
DateTime<Utc>,
) {
let day = NaiveDate::from_ymd_opt(2026, 9, 23).unwrap();
let starts = NaiveTime::from_hms_milli_opt(9, 30, 15, 500).unwrap();
let local = day.and_hms_milli_opt(9, 30, 15, 250).unwrap();
let zoned = DateTime::parse_from_rfc3339("2026-09-23T09:30:15+02:00").unwrap();
let instant = zoned.with_timezone(&Utc);
(day, starts, local, zoned, instant)
}
#[drizzle::test]
fn chrono_values_round_trip(db: &mut TestDb<ChronoSchema>) {
let ChronoSchema { events } = schema;
let (day, starts, local, zoned, instant) = values();
db.insert(events)
.values([InsertChronoEvent::new(day, starts, local, zoned, instant).with_id(1)])
.execute();
let row: SelectChronoEvent = db.select(()).from(events).get();
assert_eq!(
(row.day, row.starts, row.local, row.zoned, row.instant),
(day, starts, local, zoned, instant)
);
let (selected_day, selected_starts, selected_local, selected_instant): (
NaiveDate,
NaiveTime,
NaiveDateTime,
DateTime<Utc>,
) = db
.select((events.day, events.starts, events.local, events.instant))
.from(events)
.get();
assert_eq!(
(
selected_day,
selected_starts,
selected_local,
selected_instant
),
(day, starts, local, instant)
);
let matched: Vec<SelectChronoEvent> = db
.select(())
.from(events)
.r#where(and(eq(events.local, local), eq(events.instant, instant)))
.all();
assert_eq!(matched.len(), 1);
}
#[drizzle::test]
fn chrono_values_read_sqlite_datetime_text(db: &mut TestDb<ChronoSchema>) {
let ChronoSchema { events } = schema;
result!(db.execute(SQL::raw(
r#"INSERT INTO "chrono_events" ("id", "day", "starts", "local", "zoned", "instant")
VALUES (1, '2026-09-23', '09:30:15', '2026-09-23 09:30:15', '2026-09-23 07:30:15', '2026-09-23 07:30:15')"#
)))?;
let local = NaiveDate::from_ymd_opt(2026, 9, 23)
.unwrap()
.and_hms_opt(9, 30, 15)
.unwrap();
let instant = DateTime::parse_from_rfc3339("2026-09-23T07:30:15Z").unwrap();
let row: SelectChronoEvent = db.select(()).from(events).get();
assert_eq!(
(row.local, row.zoned, row.instant),
(local, instant, instant.with_timezone(&Utc))
);
let (selected_local, selected_instant): (NaiveDateTime, DateTime<Utc>) =
db.select((events.local, events.instant)).from(events).get();
assert_eq!(
(selected_local, selected_instant),
(local, instant.with_timezone(&Utc))
);
}
}