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