use crate::parser::token::{BoundaryKind, EpochPrecision, TemporalUnit};
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum DateExpr {
Now,
Relative(RelativeDate, Option<TimeExpr>),
DayRef(Direction, jiff::civil::Weekday, Option<TimeExpr>),
Absolute(AbsoluteDate, Option<TimeExpr>),
TimeOnly(TimeExpr),
Epoch(EpochValue),
Offset(Direction, Vec<DurationComponent>),
OffsetFrom(Direction, Vec<DurationComponent>, Box<DateExpr>),
Arithmetic(Box<DateExpr>, ArithOp, Vec<DurationComponent>),
Range(RangeExpr),
Boundary(BoundaryKind),
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelativeDate {
Today,
Tomorrow,
Yesterday,
Overmorrow,
Ereyesterday,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Next,
Last,
This,
Future,
Past,
}
#[must_use]
#[derive(Debug, Clone, PartialEq)]
pub struct DurationComponent {
pub count: i64,
pub unit: TemporalUnit,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TimeExpr {
HourMinute(i8, i8),
HourMinuteSecond(i8, i8, i8),
HourOnly(i8),
SameTime,
}
#[must_use]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AbsoluteDate {
pub year: i16,
pub month: i8,
pub day: i8,
}
#[must_use]
#[derive(Debug, Clone, PartialEq)]
pub struct EpochValue {
pub raw: i64,
pub precision: EpochPrecision,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArithOp {
Add,
Sub,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum RangeExpr {
LastWeek,
ThisWeek,
NextWeek,
LastMonth,
ThisMonth,
NextMonth,
LastYear,
ThisYear,
NextYear,
Quarter(i16, i8),
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
#[test]
fn date_expr_relative_with_time() {
let expr = DateExpr::Relative(RelativeDate::Tomorrow, Some(TimeExpr::HourMinute(15, 30)));
assert!(matches!(
expr,
DateExpr::Relative(RelativeDate::Tomorrow, Some(_))
));
}
#[test]
fn duration_component_construction() {
let dc = DurationComponent {
count: 3,
unit: TemporalUnit::Hour,
};
assert_eq!(dc.count, 3);
assert_eq!(dc.unit, TemporalUnit::Hour);
}
#[test]
fn epoch_value_construction() {
let ev = EpochValue {
raw: 1735689600,
precision: EpochPrecision::Seconds,
};
assert_eq!(ev.raw, 1735689600);
assert_eq!(ev.precision, EpochPrecision::Seconds);
}
#[test]
fn boundary_expr() {
let expr = DateExpr::Boundary(BoundaryKind::Sod);
assert!(matches!(expr, DateExpr::Boundary(BoundaryKind::Sod)));
}
#[test]
fn hour_only_time_expr() {
let t = TimeExpr::HourOnly(18);
assert!(matches!(t, TimeExpr::HourOnly(18)));
assert_ne!(TimeExpr::HourOnly(18), TimeExpr::HourMinute(18, 0));
}
#[test]
fn extension_types_exist() {
let _ = DateExpr::Arithmetic(
Box::new(DateExpr::Now),
ArithOp::Add,
vec![DurationComponent {
count: 1,
unit: TemporalUnit::Day,
}],
);
let _ = DateExpr::Range(RangeExpr::LastWeek);
}
}