opening_hours_syntax/rules/
time.rs1use std::cmp::Ordering;
2use std::fmt::Display;
3use std::ops::Range;
4
5use chrono::Duration;
6
7use crate::display::write_selector;
8use crate::extended_time::ExtendedTime;
9
10#[derive(Clone, Debug, Hash, PartialEq, Eq)]
13pub struct TimeSelector {
14 pub time: Vec<TimeSpan>,
15}
16
17impl TimeSelector {
18 pub(crate) fn is_00_24(&self) -> bool {
20 self.time.len() == 1
21 && self.time.first()
22 == Some(&TimeSpan::fixed_range(
23 ExtendedTime::MIDNIGHT_00,
24 ExtendedTime::MIDNIGHT_24,
25 ))
26 }
27}
28
29impl TimeSelector {
30 #[inline]
31 pub fn new(time: Vec<TimeSpan>) -> Self {
32 if time.is_empty() {
33 Self::default()
34 } else {
35 Self { time }
36 }
37 }
38}
39
40impl Default for TimeSelector {
41 #[inline]
42 fn default() -> Self {
43 Self {
44 time: vec![TimeSpan::fixed_range(
45 ExtendedTime::MIDNIGHT_00,
46 ExtendedTime::MIDNIGHT_24,
47 )],
48 }
49 }
50}
51
52impl Display for TimeSelector {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write_selector(f, &self.time)
55 }
56}
57
58#[derive(Clone, Debug, Hash, PartialEq, Eq)]
61pub struct TimeSpan {
62 pub range: Range<Time>,
63 pub open_end: bool,
64 pub repeats: Option<Duration>,
65}
66
67impl TimeSpan {
68 #[inline]
69 pub const fn fixed_range(start: ExtendedTime, end: ExtendedTime) -> Self {
70 Self {
71 range: Time::Fixed(start)..Time::Fixed(end),
72 open_end: false,
73 repeats: None,
74 }
75 }
76}
77
78impl Display for TimeSpan {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 write!(f, "{}", self.range.start)?;
81
82 if !self.open_end || self.range.end != Time::Fixed(ExtendedTime::MIDNIGHT_24) {
83 write!(f, "-{}", self.range.end)?;
84 }
85
86 if self.open_end {
87 write!(f, "+")?;
88 }
89
90 if let Some(repeat) = self.repeats {
91 if repeat.num_hours() > 0 {
92 write!(f, "{:02}:", repeat.num_hours())?;
93 }
94
95 write!(f, "{:02}", repeat.num_minutes() % 60)?;
96 }
97
98 Ok(())
99 }
100}
101
102#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
105pub enum Time {
106 Fixed(ExtendedTime),
107 Variable(VariableTime),
108}
109
110impl Display for Time {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 match self {
113 Self::Fixed(time) => write!(f, "{time}"),
114 Self::Variable(time) => write!(f, "{time}"),
115 }
116 }
117}
118
119#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
122pub struct VariableTime {
123 pub event: TimeEvent,
124 pub offset: i16,
125}
126
127impl Display for VariableTime {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 write!(f, "{}", self.event)?;
130
131 match self.offset.cmp(&0) {
132 Ordering::Less => write!(f, "{}", self.offset),
133 Ordering::Greater => write!(f, "+{}", self.offset),
134 Ordering::Equal => Ok(()),
135 }
136 }
137}
138
139#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
142pub enum TimeEvent {
143 Dawn,
144 Sunrise,
145 Sunset,
146 Dusk,
147}
148
149impl TimeEvent {
150 pub const fn as_str(&self) -> &'static str {
151 match self {
152 Self::Dawn => "dawn",
153 Self::Sunrise => "sunrise",
154 Self::Sunset => "sunset",
155 Self::Dusk => "dusk",
156 }
157 }
158}
159
160impl Display for TimeEvent {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 write!(f, "{}", self.as_str())
163 }
164}