1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
use chrono::{DateTime, Datelike, Utc};
use diesel::{
backend::Backend,
deserialize::{self, FromSql, FromSqlRow},
expression::AsExpression,
serialize::{self, ToSql},
sql_types::Text,
sqlite::Sqlite,
};
use serde::{Deserialize, Serialize};
#[derive(
Eq,
PartialEq,
Ord,
PartialOrd,
Serialize,
Deserialize,
Copy,
Clone,
Debug,
AsExpression,
FromSqlRow,
)]
#[diesel(sql_type=Text)]
pub struct DateTimeUtc(DateTime<Utc>);
impl DateTimeUtc {
pub fn day_diff(&self, other: &DateTimeUtc) -> u32 {
self.0
.num_days_from_ce()
.abs_diff(other.0.num_days_from_ce())
}
pub fn new(date_time_utc: DateTime<Utc>) -> Self {
Self(date_time_utc)
}
pub fn now() -> Self {
Self(Utc::now())
}
}
impl ToSql<Text, Sqlite> for DateTimeUtc {
fn to_sql<'b>(
&'b self,
out: &mut diesel::serialize::Output<'b, '_, Sqlite>,
) -> serialize::Result {
out.set_value(self.0.to_rfc3339());
Ok(diesel::serialize::IsNull::No)
}
}
impl FromSql<Text, Sqlite> for DateTimeUtc {
fn from_sql(bytes: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<DateTimeUtc> {
let str: String = FromSql::<Text, Sqlite>::from_sql(bytes)?;
let date_time = str.as_str().parse::<DateTime<Utc>>()?;
Ok(DateTimeUtc(date_time))
}
}
#[cfg(test)]
mod test {
use chrono::TimeZone;
use super::*;
#[test]
fn given_midnight_when_day_diff_next_midnight_less_1s_then_return_0() {
let start = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap().to_utc());
let end = DateTimeUtc::new(
Utc.with_ymd_and_hms(2000, 1, 1, 23, 59, 59)
.unwrap()
.to_utc(),
);
let day_diff = start.day_diff(&end);
let neg_day_diff = end.day_diff(&start);
assert_eq!(day_diff, 0);
assert_eq!(day_diff, neg_day_diff);
}
#[test]
fn given_midnight_when_day_diff_next_midnight_then_return_1() {
let start = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap().to_utc());
let end = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 2, 0, 0, 0).unwrap().to_utc());
let day_diff = start.day_diff(&end);
let neg_day_diff = end.day_diff(&start);
assert_eq!(day_diff, 1);
assert_eq!(day_diff, neg_day_diff);
}
#[test]
fn given_midnight_less_1s_when_day_diff_midnight_then_return_1() {
let start = DateTimeUtc::new(
Utc.with_ymd_and_hms(2000, 1, 1, 23, 59, 59)
.unwrap()
.to_utc(),
);
let end = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 2, 0, 0, 0).unwrap().to_utc());
let day_diff = start.day_diff(&end);
let neg_day_diff = end.day_diff(&start);
assert_eq!(day_diff, 1);
assert_eq!(day_diff, neg_day_diff);
}
}
|