formualizer_eval/builtins/datetime/
today_now.rs1use super::serial::{date_to_serial_for, datetime_to_serial_for};
4use crate::function::Function;
5use crate::traits::{ArgumentHandle, FunctionContext};
6use formualizer_common::{ExcelError, LiteralValue};
7use formualizer_macros::func_caps;
8
9#[derive(Debug)]
11pub struct TodayFn;
12
13impl Function for TodayFn {
14 func_caps!(VOLATILE);
15
16 fn name(&self) -> &'static str {
17 "TODAY"
18 }
19
20 fn min_args(&self) -> usize {
21 0
22 }
23
24 fn eval<'a, 'b, 'c>(
25 &self,
26 _args: &'c [ArgumentHandle<'a, 'b>],
27 ctx: &dyn FunctionContext<'b>,
28 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
29 let today = ctx.timezone().today();
30 let serial = date_to_serial_for(ctx.date_system(), &today);
31 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
32 serial,
33 )))
34 }
35}
36
37#[derive(Debug)]
39pub struct NowFn;
40
41impl Function for NowFn {
42 func_caps!(VOLATILE);
43
44 fn name(&self) -> &'static str {
45 "NOW"
46 }
47
48 fn min_args(&self) -> usize {
49 0
50 }
51
52 fn eval<'a, 'b, 'c>(
53 &self,
54 _args: &'c [ArgumentHandle<'a, 'b>],
55 ctx: &dyn FunctionContext<'b>,
56 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
57 let now = ctx.timezone().now();
58 let serial = datetime_to_serial_for(ctx.date_system(), &now);
59 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
60 serial,
61 )))
62 }
63}
64
65pub fn register_builtins() {
66 use std::sync::Arc;
67 crate::function_registry::register_function(Arc::new(TodayFn));
68 crate::function_registry::register_function(Arc::new(NowFn));
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use crate::test_workbook::TestWorkbook;
75 use std::sync::Arc;
76
77 #[test]
78 fn test_today_volatility() {
79 let wb = TestWorkbook::new().with_function(Arc::new(TodayFn));
80 let ctx = wb.interpreter();
81 let f = ctx.context.get_function("", "TODAY").unwrap();
82
83 let result = f
85 .dispatch(&[], &ctx.function_context(None))
86 .unwrap()
87 .into_literal();
88 match result {
89 LiteralValue::Number(n) => {
90 assert!(n > 0.0);
92 assert_eq!(n.trunc(), n);
94 }
95 _ => panic!("TODAY should return a number"),
96 }
97
98 }
100
101 #[test]
102 fn test_now_volatility() {
103 let wb = TestWorkbook::new().with_function(Arc::new(NowFn));
104 let ctx = wb.interpreter();
105 let f = ctx.context.get_function("", "NOW").unwrap();
106
107 let result = f
109 .dispatch(&[], &ctx.function_context(None))
110 .unwrap()
111 .into_literal();
112 match result {
113 LiteralValue::Number(n) => {
114 assert!(n > 0.0);
116 }
120 _ => panic!("NOW should return a number"),
121 }
122
123 }
125}