1use chrono::{DateTime, Duration, TimeZone, Utc};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4pub struct DateTimeRange(pub DateTime<Utc>, pub DateTime<Utc>, pub Duration);
5
6impl Iterator for DateTimeRange {
7 type Item = DateTime<Utc>;
8 fn next(&mut self) -> Option<Self::Item> {
9 if self.0 <= self.1 {
10 let next = self.0 + self.2;
11 Some(std::mem::replace(&mut self.0, next))
12 } else {
13 None
14 }
15 }
16}
17
18#[derive(Deserialize, Serialize, Debug)]
19pub struct TimestampBuilder {
20 #[serde(default = "default_start")]
23 pub start: DateTime<Utc>,
24 #[serde(default = "default_end")]
26 pub end: DateTime<Utc>,
27 #[serde(with = "duration_format", default = "default_interval")]
28 pub interval: Duration,
29 #[serde(default = "default_batch_size")]
30 pub batch_size: usize,
31}
32
33const FORMAT: &'static str = "%Y-%m-%d %H:%M";
34
35pub fn default_start() -> DateTime<Utc> {
36 Utc.datetime_from_str("2019-09-13 04:00", FORMAT).unwrap()
37}
38
39pub fn default_end() -> DateTime<Utc> {
40 Utc::now()
41}
42
43pub fn default_interval() -> Duration {
44 Duration::milliseconds(900000)
45}
46
47pub fn default_batch_size() -> usize {
48 499
49}
50
51pub mod duration_format {
52 use super::*;
53
54 pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: Serializer,
57 {
58 let s = serialize_duration(duration).map_err(serde::ser::Error::custom)?;
59 serializer.serialize_str(&s)
60 }
61
62 pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
63 where
64 D: Deserializer<'de>,
65 {
66 let s = String::deserialize(deserializer)?;
67 match s.as_str() {
68 "1m" => Ok(Duration::milliseconds(60000)),
69 "5m" => Ok(Duration::milliseconds(300000)),
70 "15m" => Ok(Duration::milliseconds(900000)),
71 "1h" => Ok(Duration::milliseconds(3600000)),
72 "4h" => Ok(Duration::milliseconds(14400000)),
73 "1d" => Ok(Duration::milliseconds(86400000)),
74 _ => Err(serde::de::Error::custom("unexpected time interval")),
75 }
76 }
77
78 pub fn serialize_duration(duration: &Duration) -> std::io::Result<&'static str> {
79 match duration.num_minutes() {
80 1 => Ok("1m"),
81 5 => Ok("5m"),
82 15 => Ok("15m"),
83 60 => Ok("1h"),
84 240 => Ok("4h"),
85 1440 => Ok("1d"),
86 _ => unimplemented!("not implemented interaval"),
87 }
88 }
89}