1use crate::parser::token::{BoundaryKind, EpochPrecision, TemporalUnit};
7
8#[non_exhaustive]
10#[derive(Debug, Clone, PartialEq)]
11pub enum DateExpr {
12 Now,
14 Relative(RelativeDate, Option<TimeExpr>),
16 DayRef(Direction, jiff::civil::Weekday, Option<TimeExpr>),
18 Absolute(AbsoluteDate, Option<TimeExpr>),
20 TimeOnly(TimeExpr),
22 Epoch(EpochValue),
24 Offset(Direction, Vec<DurationComponent>),
26 OffsetFrom(Direction, Vec<DurationComponent>, Box<DateExpr>),
28
29 Arithmetic(Box<DateExpr>, ArithOp, Vec<DurationComponent>),
31 Range(RangeExpr),
33
34 Boundary(BoundaryKind),
36}
37
38#[non_exhaustive]
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum RelativeDate {
42 Today,
43 Tomorrow,
44 Yesterday,
45 Overmorrow,
46 Ereyesterday,
47}
48
49#[non_exhaustive]
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum Direction {
53 Next,
54 Last,
55 This,
56 Future,
57 Past,
58}
59
60#[must_use]
62#[derive(Debug, Clone, PartialEq)]
63pub struct DurationComponent {
64 pub count: i64,
65 pub unit: TemporalUnit,
66}
67
68#[non_exhaustive]
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum TimeExpr {
72 HourMinute(i8, i8),
73 HourMinuteSecond(i8, i8, i8),
74 HourOnly(i8),
76 SameTime,
78}
79
80#[must_use]
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct AbsoluteDate {
84 pub year: i16,
85 pub month: i8,
86 pub day: i8,
87}
88
89#[must_use]
91#[derive(Debug, Clone, PartialEq)]
92pub struct EpochValue {
93 pub raw: i64,
94 pub precision: EpochPrecision,
95}
96
97#[non_exhaustive]
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum ArithOp {
101 Add,
102 Sub,
103}
104
105#[non_exhaustive]
107#[derive(Debug, Clone, PartialEq)]
108pub enum RangeExpr {
109 LastWeek,
110 ThisWeek,
111 NextWeek,
112 LastMonth,
113 ThisMonth,
114 NextMonth,
115 LastYear,
116 ThisYear,
117 NextYear,
118 Quarter(i16, i8),
119}
120
121#[cfg(test)]
122mod tests {
123 #![allow(clippy::unwrap_used, clippy::expect_used)]
124 use super::*;
125
126 #[test]
127 fn date_expr_relative_with_time() {
128 let expr = DateExpr::Relative(RelativeDate::Tomorrow, Some(TimeExpr::HourMinute(15, 30)));
129 assert!(matches!(
130 expr,
131 DateExpr::Relative(RelativeDate::Tomorrow, Some(_))
132 ));
133 }
134
135 #[test]
136 fn duration_component_construction() {
137 let dc = DurationComponent {
138 count: 3,
139 unit: TemporalUnit::Hour,
140 };
141 assert_eq!(dc.count, 3);
142 assert_eq!(dc.unit, TemporalUnit::Hour);
143 }
144
145 #[test]
146 fn epoch_value_construction() {
147 let ev = EpochValue {
148 raw: 1735689600,
149 precision: EpochPrecision::Seconds,
150 };
151 assert_eq!(ev.raw, 1735689600);
152 assert_eq!(ev.precision, EpochPrecision::Seconds);
153 }
154
155 #[test]
156 fn boundary_expr() {
157 let expr = DateExpr::Boundary(BoundaryKind::Sod);
158 assert!(matches!(expr, DateExpr::Boundary(BoundaryKind::Sod)));
159 }
160
161 #[test]
162 fn hour_only_time_expr() {
163 let t = TimeExpr::HourOnly(18);
164 assert!(matches!(t, TimeExpr::HourOnly(18)));
165 assert_ne!(TimeExpr::HourOnly(18), TimeExpr::HourMinute(18, 0));
166 }
167
168 #[test]
169 fn extension_types_exist() {
170 let _ = DateExpr::Arithmetic(
171 Box::new(DateExpr::Now),
172 ArithOp::Add,
173 vec![DurationComponent {
174 count: 1,
175 unit: TemporalUnit::Day,
176 }],
177 );
178 let _ = DateExpr::Range(RangeExpr::LastWeek);
179 }
180}