valis_core/modules/db/
serializers.rs1use std::str::FromStr;
2
3use chrono::{DateTime, Duration, NaiveDate, ParseError, Utc};
4use rusqlite::types::FromSqlError;
5use rusqlite::types::{FromSql, FromSqlResult, ValueRef};
6use serde::de::Error;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9#[derive(Debug, Clone)]
10pub struct SerializableDateTime(DateTime<Utc>);
11
12impl Serialize for SerializableDateTime {
13 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
14 where
15 S: Serializer,
16 {
17 let s = self.0.to_rfc3339();
18 serializer.serialize_str(&s)
19 }
20}
21
22impl<'de> Deserialize<'de> for SerializableDateTime {
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: Deserializer<'de>,
26 {
27 let s = String::deserialize(deserializer)?;
28 let dt = DateTime::parse_from_rfc3339(&s)
29 .map_err(Error::custom)?
30 .with_timezone(&Utc);
31 Ok(SerializableDateTime(dt))
32 }
33}
34
35impl FromSql for SerializableDateTime {
36 fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
37 match value {
38 ValueRef::Text(s) => {
39 let s = String::from_utf8(s.to_vec())
40 .map_err(|_| rusqlite::types::FromSqlError::InvalidType)?;
41 DateTime::from_str(&s)
42 .map_err(|_| FromSqlError::InvalidType)
43 .map(|dt| SerializableDateTime(dt))
44 }
45 ValueRef::Blob(b) => {
46 let s = String::from_utf8(b.to_vec())
47 .map_err(|_| rusqlite::types::FromSqlError::InvalidType)?;
48 DateTime::parse_from_rfc3339(&s)
49 .map_err(|_| rusqlite::types::FromSqlError::InvalidType)
50 .map(|dt| SerializableDateTime(dt.with_timezone(&Utc)))
51 }
52 _ => Err(FromSqlError::InvalidType),
53 }
54 }
55}
56
57impl SerializableDateTime {
58 pub fn parse_from_rfc3339(s: &str) -> Result<SerializableDateTime, ParseError> {
59 let dt = DateTime::parse_from_rfc3339(s)?;
60 Ok(SerializableDateTime(dt.with_timezone(&Utc)))
61 }
62 pub fn with_timezone(&self, tz: &Utc) -> SerializableDateTime {
63 SerializableDateTime(self.0.with_timezone(tz))
64 }
65 pub fn now() -> Self {
66 SerializableDateTime(Utc::now())
67 }
68 pub fn to_string(&self) -> String {
69 self.0.to_rfc3339()
70 }
71 pub fn add_weeks(&self, weeks: i64) -> Self {
72 SerializableDateTime(self.0 + Duration::weeks(weeks))
73 }
74 pub fn from_str(date: &str) -> Result<Self, chrono::format::ParseError> {
76 let naive_date = NaiveDate::parse_from_str(date, "%Y-%m-%d")?;
77 let datetime = DateTime::from_utc(naive_date.and_hms(0, 0, 0), Utc);
78 Ok(SerializableDateTime(datetime))
79 }
80 pub fn get_utc(&self) -> DateTime<Utc> {
81 self.0
82 }
83}