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
112
113
114
115
116
117
118
119
120
121
122
123
use chrono::{Duration, NaiveDateTime};
use std::fmt;
use strum_macros::{AsStaticStr, EnumIter, EnumString};
#[derive(Clone, Copy, PartialEq, Eq, Debug, EnumString, AsStaticStr, EnumIter, Hash)]
pub enum Model {
#[strum(
to_string = "gfs",
serialize = "gfs3",
serialize = "GFS",
serialize = "GFS3"
)]
GFS,
#[strum(
to_string = "nam",
serialize = "namm",
serialize = "NAM",
serialize = "NAMM"
)]
NAM,
#[strum(to_string = "nam4km", serialize = "NAM4KM")]
NAM4KM,
}
impl fmt::Display for Model {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::Model::*;
match *self {
GFS => write!(f, "{}", stringify!(GFS)),
NAM => write!(f, "{}", stringify!(NAM)),
NAM4KM => write!(f, "{}", stringify!(NAM4KM)),
}
}
}
impl Model {
pub fn hours_between_runs(self) -> i64 {
match self {
Model::GFS => 6,
Model::NAM => 6,
Model::NAM4KM => 6,
}
}
pub fn base_hour(self) -> i64 {
match self {
_ => 0,
}
}
pub fn all_runs(
self,
start: &NaiveDateTime,
end: &NaiveDateTime,
) -> impl Iterator<Item = NaiveDateTime> {
debug_assert!(start <= end);
let delta_t = self.hours_between_runs();
let mut round_start = start.date().and_hms(0, 0, 0) + Duration::hours(self.base_hour());
while round_start > *start {
round_start -= Duration::hours(self.hours_between_runs());
}
while round_start < *start {
round_start += Duration::hours(self.hours_between_runs());
}
while round_start > *end {
round_start -= Duration::hours(self.hours_between_runs());
}
let steps: i64 = (*end - round_start).num_hours() / self.hours_between_runs();
(0..=steps).map(move |step| round_start + Duration::hours(step * delta_t))
}
}
#[cfg(test)]
mod unit {
use super::*;
use chrono::NaiveDate;
#[test]
fn test_all_runs() {
assert_eq!(
Model::GFS.hours_between_runs(),
6,
"test pre-condition failed."
);
let start = &NaiveDate::from_ymd(2018, 9, 1).and_hms(0, 0, 0);
let end = &NaiveDate::from_ymd(2018, 9, 2).and_hms(0, 0, 0);
assert_eq!(Model::GFS.all_runs(start, end).count(), 5);
let start = &NaiveDate::from_ymd(2018, 9, 1).and_hms(0, 1, 0);
let end = &NaiveDate::from_ymd(2018, 9, 2).and_hms(0, 0, 0);
assert_eq!(Model::GFS.all_runs(start, end).count(), 4);
}
}