Skip to content

Commit c5c1788

Browse files
committed
rule
1 parent da95611 commit c5c1788

File tree

1 file changed

+107
-19
lines changed

1 file changed

+107
-19
lines changed

utils/resb/examples/time_zone_rule.rs

Lines changed: 107 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,95 @@ struct TzRule {
4747

4848
#[derive(Debug)]
4949
struct TzRuleDate {
50-
month: i8,
5150
day: i8,
5251
day_of_week: i8,
53-
seconds_of_day: i32,
54-
time_mode: i8,
52+
month: u8,
53+
millis_of_day: u32,
54+
time_mode: TimeMode,
55+
mode: RuleMode,
56+
}
57+
58+
#[derive(Debug)]
59+
enum TimeMode {
60+
Wall = 0,
61+
Standard = 1,
62+
Utc = 2,
63+
}
64+
65+
#[derive(Debug, PartialEq)]
66+
#[allow(non_camel_case_types)]
67+
enum RuleMode {
68+
DOW_IN_MONTH,
69+
DOM,
70+
DOW_GE_DOM,
71+
DOW_LE_DOM,
72+
}
73+
74+
impl TzRuleDate {
75+
fn new(
76+
mut day: i8,
77+
mut day_of_week: i8,
78+
month: u8,
79+
millis_of_day: u32,
80+
time_mode: i8,
81+
) -> Option<Self> {
82+
const GREGORIAN_MONTHS: [i8; 12] = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
83+
84+
if day == 0 {
85+
return None;
86+
}
87+
if month > 11 {
88+
return None;
89+
}
90+
if millis_of_day > 24 * 60 * 60 * 1000 {
91+
return None;
92+
}
93+
94+
let time_mode = match time_mode {
95+
0 => TimeMode::Wall,
96+
1 => TimeMode::Standard,
97+
2 => TimeMode::Utc,
98+
_ => return None,
99+
};
100+
101+
let mode;
102+
103+
if day_of_week == 0 {
104+
mode = RuleMode::DOM;
105+
} else {
106+
if day_of_week > 0 {
107+
mode = RuleMode::DOW_IN_MONTH
108+
} else {
109+
day_of_week = -day_of_week;
110+
if day > 0 {
111+
mode = RuleMode::DOW_GE_DOM;
112+
} else {
113+
day = -day;
114+
mode = RuleMode::DOW_LE_DOM;
115+
}
116+
}
117+
if day_of_week > 7 {
118+
return None;
119+
}
120+
}
121+
122+
if mode == RuleMode::DOW_IN_MONTH {
123+
if !(-5..=5).contains(&day) {
124+
return None;
125+
}
126+
} else if day < 1 || day > GREGORIAN_MONTHS[month as usize] {
127+
return None;
128+
}
129+
130+
Some(Self {
131+
day,
132+
day_of_week,
133+
month,
134+
millis_of_day,
135+
time_mode,
136+
mode,
137+
})
138+
}
55139
}
56140

57141
impl<'de> Deserialize<'de> for ZoneInfo64<'de> {
@@ -191,20 +275,22 @@ impl<'de> Deserialize<'de> for ZoneInfo64<'de> {
191275
key,
192276
TzRule {
193277
additional_offset_secs: value[10],
194-
start: TzRuleDate {
195-
month: value[0] as i8,
196-
day: value[1] as i8,
197-
day_of_week: value[2] as i8,
198-
seconds_of_day: value[3],
199-
time_mode: value[4] as i8,
200-
},
201-
end: TzRuleDate {
202-
month: value[5] as i8,
203-
day: value[6] as i8,
204-
day_of_week: value[7] as i8,
205-
seconds_of_day: value[8],
206-
time_mode: value[9] as i8,
207-
},
278+
start: TzRuleDate::new(
279+
value[1] as i8,
280+
value[2] as i8,
281+
value[0] as u8,
282+
value[3] as u32,
283+
value[4] as i8,
284+
)
285+
.unwrap(),
286+
end: TzRuleDate::new(
287+
value[6] as i8,
288+
value[7] as i8,
289+
value[5] as u8,
290+
value[8] as u32,
291+
value[9] as i8,
292+
)
293+
.unwrap(),
208294
},
209295
));
210296
}
@@ -445,14 +531,16 @@ impl Rule<'_> {
445531
let _ = self.inner.start.month;
446532
let _ = self.inner.start.day;
447533
let _ = self.inner.start.day_of_week;
448-
let _ = self.inner.start.seconds_of_day;
534+
let _ = self.inner.start.millis_of_day;
449535
let _ = self.inner.start.time_mode;
536+
let _ = self.inner.start.mode;
450537

451538
let _ = self.inner.end.month;
452539
let _ = self.inner.end.day;
453540
let _ = self.inner.end.day_of_week;
454-
let _ = self.inner.end.seconds_of_day;
541+
let _ = self.inner.end.millis_of_day;
455542
let _ = self.inner.end.time_mode;
543+
let _ = self.inner.end.mode;
456544

457545
Transition {
458546
transition,

0 commit comments

Comments
 (0)