sbrd_gen/generator/primitive/
date_time_generator.rs1use crate::builder::{GeneratorBuilder, ValueBound};
2use crate::error::{BuildError, GenerateError};
3use crate::eval::Evaluator;
4use crate::generator::{GeneratorBase, Randomizer};
5use crate::value::{DataValue, DataValueMap, SbrdDate, SbrdDateTime, DATE_TIME_DEFAULT_FORMAT};
6use crate::GeneratorType;
7
8#[derive(Debug, PartialEq, Clone)]
18pub struct DateTimeGenerator {
19 nullable: bool,
20 format: String,
21 range: ValueBound<SbrdDateTime>,
22}
23
24impl<R: Randomizer + ?Sized> GeneratorBase<R> for DateTimeGenerator {
25 fn create(builder: GeneratorBuilder) -> Result<Self, BuildError>
26 where
27 Self: Sized,
28 {
29 let GeneratorBuilder {
30 generator_type,
31 nullable,
32 range,
33 format,
34 ..
35 } = builder;
36
37 if generator_type != GeneratorType::DateTime {
38 return Err(BuildError::InvalidType(generator_type));
39 }
40
41 let default_range = Self::default_range();
42 let _range = match range {
43 None => default_range,
44 Some(r) => r
45 .try_convert_with(|s| {
46 SbrdDateTime::parse_from_str(&s.to_parse_string(), DATE_TIME_DEFAULT_FORMAT)
47 .map_err(|e| {
48 BuildError::FailParseValue(
49 s.to_parse_string(),
50 "DateTime".to_string(),
51 e.to_string(),
52 )
53 })
54 })
55 .map(|range| {
56 range.without_no_bound_from_other(default_range)
58 })?,
59 };
60 if _range.is_empty() {
61 return Err(BuildError::RangeEmpty(_range.convert_into()));
62 }
63
64 Ok(Self {
65 nullable,
66 format: format.unwrap_or_else(|| DATE_TIME_DEFAULT_FORMAT.to_string()),
67 range: _range,
68 })
69 }
70
71 fn is_nullable(&self) -> bool {
72 self.nullable
73 }
74
75 fn generate_without_null(
76 &self,
77 rng: &mut R,
78 context: &DataValueMap<&str>,
79 ) -> Result<DataValue, GenerateError> {
80 let timestamp_range = self.range.convert_with(|date_time| date_time.timestamp());
81 let timestamp_value = rng.gen_range(timestamp_range);
82 let date_time_value =
83 SbrdDateTime::from_timestamp_opt(timestamp_value, 0).ok_or_else(|| {
84 GenerateError::FailGenerate(format!(
85 "Fail parse date time from timestamp: {}",
86 timestamp_value
87 ))
88 })?;
89
90 let evaluator = Evaluator::new(context);
91 let format = evaluator.format_script(&self.format).map_err(|e| {
92 GenerateError::FailEval(
93 e,
94 self.format.to_string(),
95 context
96 .clone()
97 .into_iter()
98 .map(|(k, v)| (k.to_string(), v))
99 .collect::<DataValueMap<String>>(),
100 )
101 })?;
102
103 Ok(DataValue::String(
104 date_time_value.format(&format).to_string(),
105 ))
106 }
107}
108
109impl DateTimeGenerator {
110 #[inline]
111 fn min_date_time() -> SbrdDateTime {
112 SbrdDate::from_ymd(1900, 1, 1).and_hms(0, 0, 0)
113 }
114 #[inline]
115 fn upper_limit_date_time() -> SbrdDateTime {
116 SbrdDate::from_ymd(2151, 1, 1).and_hms(0, 0, 0)
117 }
118
119 fn default_range() -> ValueBound<SbrdDateTime> {
120 ValueBound::new(
121 Some(Self::min_date_time()),
122 Some((false, Self::upper_limit_date_time())),
123 )
124 }
125}