fts_sqlite/types/
datetime.rs

1//! DateTime type for temporal data in flow trading.
2//!
3//! This module provides a [`DateTime`] type that represents UTC timestamps with
4//! subsecond precision. It wraps `time::PrimitiveDateTime` and ensures all
5//! serialization happens in RFC3339 format for consistency across the system.
6
7use std::{borrow::Borrow, fmt::Display};
8use time::format_description::well_known::Rfc3339;
9
10/// A type that represents a datetime with subsecond precision.
11///
12/// This type is used throughout the flow trading system to represent timestamps
13/// for events, validity periods, and historical records. It ensures:
14///
15/// - All times are stored and processed in UTC
16/// - Serialization/deserialization uses RFC3339 format
17/// - SQLite storage uses the appropriate datetime type
18///
19/// # Examples
20///
21/// ```
22/// # use fts_sqlite::types::DateTime;
23/// # use time::OffsetDateTime;
24/// let now = OffsetDateTime::now_utc();
25/// let datetime = DateTime::from(now);
26/// println!("{}", datetime); // Prints in RFC3339 format
27/// ```
28#[derive(
29    Debug,
30    Clone,
31    Copy,
32    PartialEq,
33    Eq,
34    PartialOrd,
35    Ord,
36    serde::Serialize,
37    serde::Deserialize,
38    sqlx::Type,
39)]
40#[serde(from = "DateTimeDto", into = "DateTimeDto")]
41#[sqlx(transparent)]
42pub struct DateTime(time::PrimitiveDateTime);
43
44impl Display for DateTime {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        let value: time::OffsetDateTime = self.clone().into();
47        write!(f, "{}", value.format(&Rfc3339).unwrap())
48    }
49}
50
51impl<T: Borrow<time::OffsetDateTime>> From<T> for DateTime {
52    fn from(value: T) -> Self {
53        let utc = value.borrow().to_offset(time::UtcOffset::UTC);
54        Self(time::PrimitiveDateTime::new(utc.date(), utc.time()))
55    }
56}
57
58impl Into<time::OffsetDateTime> for DateTime {
59    fn into(self) -> time::OffsetDateTime {
60        self.0.assume_utc()
61    }
62}
63
64// This is a helper type that ensures (de)serialization happens with respect to RFC3339
65
66#[derive(serde::Serialize, serde::Deserialize)]
67struct DateTimeDto(#[serde(with = "time::serde::rfc3339")] time::OffsetDateTime);
68
69impl From<DateTimeDto> for DateTime {
70    fn from(value: DateTimeDto) -> Self {
71        value.0.into()
72    }
73}
74
75impl Into<DateTimeDto> for DateTime {
76    fn into(self) -> DateTimeDto {
77        DateTimeDto(self.into())
78    }
79}
80
81#[cfg(feature = "schemars")]
82impl schemars::JsonSchema for DateTime {
83    fn inline_schema() -> bool {
84        true
85    }
86
87    fn schema_name() -> std::borrow::Cow<'static, str> {
88        "DateTime".into()
89    }
90
91    fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
92        schemars::json_schema!({
93            "type": "string",
94            "format": "date-time",
95        })
96    }
97}