bo4e_core/com/
date_range.rs1use chrono::NaiveDate;
4use serde::{Deserialize, Serialize};
5
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct DateRange {
27 #[serde(flatten)]
29 pub meta: Bo4eMeta,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub start_date: Option<NaiveDate>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub end_date: Option<NaiveDate>,
38}
39
40impl Bo4eObject for DateRange {
41 fn type_name_german() -> &'static str {
42 "Datumsbereich"
43 }
44
45 fn type_name_english() -> &'static str {
46 "DateRange"
47 }
48
49 fn meta(&self) -> &Bo4eMeta {
50 &self.meta
51 }
52
53 fn meta_mut(&mut self) -> &mut Bo4eMeta {
54 &mut self.meta
55 }
56}
57
58impl DateRange {
59 pub fn new(start: NaiveDate, end: NaiveDate) -> Self {
61 Self {
62 start_date: Some(start),
63 end_date: Some(end),
64 ..Default::default()
65 }
66 }
67
68 pub fn year(year: i32) -> Self {
70 Self {
71 start_date: NaiveDate::from_ymd_opt(year, 1, 1),
72 end_date: NaiveDate::from_ymd_opt(year, 12, 31),
73 ..Default::default()
74 }
75 }
76
77 pub fn contains(&self, date: NaiveDate) -> bool {
79 let after_start = self.start_date.map_or(true, |s| date >= s);
80 let before_end = self.end_date.map_or(true, |e| date <= e);
81 after_start && before_end
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_date_range_creation() {
91 let start = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
92 let end = NaiveDate::from_ymd_opt(2024, 12, 31).unwrap();
93
94 let range = DateRange::new(start, end);
95 assert_eq!(range.start_date, Some(start));
96 assert_eq!(range.end_date, Some(end));
97 }
98
99 #[test]
100 fn test_year_range() {
101 let range = DateRange::year(2024);
102 assert_eq!(range.start_date, NaiveDate::from_ymd_opt(2024, 1, 1));
103 assert_eq!(range.end_date, NaiveDate::from_ymd_opt(2024, 12, 31));
104 }
105
106 #[test]
107 fn test_contains() {
108 let range = DateRange::year(2024);
109 let mid = NaiveDate::from_ymd_opt(2024, 6, 15).unwrap();
110 assert!(range.contains(mid));
111
112 let before = NaiveDate::from_ymd_opt(2023, 12, 31).unwrap();
113 assert!(!range.contains(before));
114 }
115
116 #[test]
117 fn test_roundtrip() {
118 let range = DateRange::year(2024);
119 let json = serde_json::to_string(&range).unwrap();
120 let parsed: DateRange = serde_json::from_str(&json).unwrap();
121 assert_eq!(range, parsed);
122 }
123
124 #[test]
125 fn test_bo4e_object_impl() {
126 assert_eq!(DateRange::type_name_german(), "Datumsbereich");
127 assert_eq!(DateRange::type_name_english(), "DateRange");
128 }
129}