stuart_core/functions/parsers/
dateformat.rs1use crate::functions::{Function, FunctionParser};
2use crate::parse::{ParseError, RawFunction};
3use crate::process::{ProcessError, Scope};
4use crate::{quiet_assert, TracebackError};
5
6pub struct DateFormatParser;
8
9#[derive(Debug, Clone)]
10#[allow(dead_code)]
11pub struct DateFormatFunction {
12 variable_name: String,
13 format: String,
14}
15
16impl FunctionParser for DateFormatParser {
17 fn name(&self) -> &'static str {
18 "dateformat"
19 }
20
21 fn parse(&self, raw: RawFunction) -> Result<Box<dyn Function>, ParseError> {
22 quiet_assert!(raw.positional_args.len() == 2)?;
23 quiet_assert!(raw.named_args.is_empty())?;
24
25 let variable_name = raw.positional_args[0]
26 .as_variable()
27 .ok_or(ParseError::InvalidArgument)?
28 .to_string();
29
30 let format = raw.positional_args[1]
31 .as_string()
32 .ok_or(ParseError::InvalidArgument)?
33 .to_string();
34
35 Ok(Box::new(DateFormatFunction {
36 variable_name,
37 format,
38 }))
39 }
40}
41
42impl Function for DateFormatFunction {
43 fn name(&self) -> &'static str {
44 "dateformat"
45 }
46
47 #[cfg(feature = "date")]
48 fn execute(&self, scope: &mut Scope) -> Result<(), TracebackError<ProcessError>> {
49 use chrono::{NaiveTime, Utc};
50 use dateparser::parse_with;
51
52 let self_token = scope.tokens.current().unwrap().clone();
53
54 let variable = scope.get_variable(&self.variable_name).ok_or_else(|| {
55 self_token.traceback(ProcessError::UndefinedVariable(self.variable_name.clone()))
56 })?;
57
58 let string = variable.as_str().ok_or_else(|| {
59 self_token.traceback(ProcessError::InvalidDataType {
60 variable: self.variable_name.clone(),
61 expected: "string".to_string(),
62 found: String::new(),
63 })
64 })?;
65
66 let date = std::panic::catch_unwind(|| {
67 parse_with(string, &Utc, NaiveTime::from_hms_opt(0, 0, 0).unwrap())
68 .ok()
69 .map(|d| d.format(&self.format).to_string())
70 .ok_or(ProcessError::InvalidDate)
71 })
72 .map_err(|_| self_token.traceback(ProcessError::InvalidDate))?
73 .map_err(|_| self_token.traceback(ProcessError::InvalidDate))?;
74
75 scope.output(date).map_err(|e| self_token.traceback(e))?;
76
77 Ok(())
78 }
79
80 #[cfg(not(feature = "date"))]
81 fn execute(&self, scope: &mut Scope) -> Result<(), TracebackError<ProcessError>> {
82 let self_token = scope.tokens.current().unwrap();
83
84 Err(self_token.traceback(ProcessError::FeatureNotEnabled("date".to_string())))
85 }
86}