botserver/src/basic/keywords/datetime/now.rs
Rodrigo Rodriguez (Pragmatismo) 5da86bbef2 Fix clippy warnings: match arms, async/await, Debug impls, formatting
- Fix match arms with identical bodies by consolidating patterns
- Fix case-insensitive file extension comparisons using eq_ignore_ascii_case
- Fix unnecessary Debug formatting in log/format macros
- Fix clone_from usage instead of clone assignment
- Fix let...else patterns where appropriate
- Fix format! append to String using write! macro
- Fix unwrap_or with function calls to use unwrap_or_else
- Add missing fields to manual Debug implementations
- Fix duplicate code in if blocks
- Add type aliases for complex types
- Rename struct fields to avoid common prefixes
- Various other clippy warning fixes

Note: Some 'unused async' warnings remain for functions that are
called with .await but don't contain await internally - these are
kept async for API compatibility.
2025-12-26 08:59:25 -03:00

313 lines
9.4 KiB
Rust

use crate::shared::models::UserSession;
use crate::shared::state::AppState;
use chrono::{Datelike, Local, Timelike, Utc};
use log::debug;
use rhai::{Dynamic, Engine, Map};
use std::sync::Arc;
fn create_datetime_map(local: chrono::DateTime<Local>) -> Map {
let mut map = Map::new();
map.insert("year".into(), Dynamic::from(i64::from(local.year())));
map.insert("month".into(), Dynamic::from(i64::from(local.month())));
map.insert("day".into(), Dynamic::from(i64::from(local.day())));
map.insert("hour".into(), Dynamic::from(i64::from(local.hour())));
map.insert("minute".into(), Dynamic::from(i64::from(local.minute())));
map.insert("second".into(), Dynamic::from(i64::from(local.second())));
map.insert(
"weekday".into(),
Dynamic::from(i64::from(local.weekday().num_days_from_sunday()) + 1),
);
let weekday_name = match local.weekday().num_days_from_sunday() {
0 => "Sunday",
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6 => "Saturday",
_ => "Unknown",
};
map.insert(
"weekday_name".into(),
Dynamic::from(weekday_name.to_string()),
);
let month_name = match local.month() {
1 => "January",
2 => "February",
3 => "March",
4 => "April",
5 => "May",
6 => "June",
7 => "July",
8 => "August",
9 => "September",
10 => "October",
11 => "November",
12 => "December",
_ => "Unknown",
};
map.insert("month_name".into(), Dynamic::from(month_name.to_string()));
map.insert("timestamp".into(), Dynamic::from(local.timestamp()));
map.insert(
"formatted".into(),
Dynamic::from(local.format("%Y-%m-%d %H:%M:%S").to_string()),
);
map.insert(
"date".into(),
Dynamic::from(local.format("%Y-%m-%d").to_string()),
);
map.insert(
"time".into(),
Dynamic::from(local.format("%H:%M:%S").to_string()),
);
map.insert(
"iso".into(),
Dynamic::from(local.format("%Y-%m-%dT%H:%M:%S%z").to_string()),
);
let quarter = ((local.month() - 1) / 3) + 1;
map.insert("quarter".into(), Dynamic::from(i64::from(quarter)));
map.insert(
"day_of_year".into(),
Dynamic::from(i64::from(local.ordinal())),
);
let is_weekend =
local.weekday().num_days_from_sunday() == 0 || local.weekday().num_days_from_sunday() == 6;
map.insert("is_weekend".into(), Dynamic::from(is_weekend));
let is_pm = local.hour() >= 12;
map.insert("is_pm".into(), Dynamic::from(is_pm));
map.insert(
"ampm".into(),
Dynamic::from(if is_pm { "PM" } else { "AM" }.to_string()),
);
let hour12 = if local.hour() == 0 {
12
} else if local.hour() > 12 {
local.hour() - 12
} else {
local.hour()
};
map.insert("hour12".into(), Dynamic::from(i64::from(hour12)));
map
}
pub fn now_keyword(_state: &Arc<AppState>, _user: UserSession, engine: &mut Engine) {
engine.register_fn("NOW", || -> Map { create_datetime_map(Local::now()) });
engine.register_fn("now", || -> Map { create_datetime_map(Local::now()) });
engine.register_fn("NOW_UTC", || -> Map {
let utc = Utc::now();
let local = utc.with_timezone(&Local);
create_datetime_map(local)
});
engine.register_fn("NOW_STR", || -> String {
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
});
engine.register_fn("now_str", || -> String {
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
});
debug!("Registered NOW keyword with .property access");
}
pub fn today_keyword(_state: &Arc<AppState>, _user: UserSession, engine: &mut Engine) {
engine.register_fn("TODAY", || -> Map {
let now = Local::now();
let mut map = Map::new();
map.insert("year".into(), Dynamic::from(i64::from(now.year())));
map.insert("month".into(), Dynamic::from(i64::from(now.month())));
map.insert("day".into(), Dynamic::from(i64::from(now.day())));
map.insert(
"weekday".into(),
Dynamic::from(i64::from(now.weekday().num_days_from_sunday()) + 1),
);
map.insert(
"formatted".into(),
Dynamic::from(now.format("%Y-%m-%d").to_string()),
);
map.insert(
"day_of_year".into(),
Dynamic::from(i64::from(now.ordinal())),
);
let is_weekend =
now.weekday().num_days_from_sunday() == 0 || now.weekday().num_days_from_sunday() == 6;
map.insert("is_weekend".into(), Dynamic::from(is_weekend));
let quarter = ((now.month() - 1) / 3) + 1;
map.insert("quarter".into(), Dynamic::from(i64::from(quarter)));
map
});
engine.register_fn("today", || -> Map {
let now = Local::now();
let mut map = Map::new();
map.insert("year".into(), Dynamic::from(i64::from(now.year())));
map.insert("month".into(), Dynamic::from(i64::from(now.month())));
map.insert("day".into(), Dynamic::from(i64::from(now.day())));
map.insert(
"weekday".into(),
Dynamic::from(i64::from(now.weekday().num_days_from_sunday()) + 1),
);
map.insert(
"formatted".into(),
Dynamic::from(now.format("%Y-%m-%d").to_string()),
);
map
});
engine.register_fn("TODAY_STR", || -> String {
Local::now().format("%Y-%m-%d").to_string()
});
engine.register_fn("today_str", || -> String {
Local::now().format("%Y-%m-%d").to_string()
});
debug!("Registered TODAY keyword with .property access");
}
pub fn time_keyword(_state: &Arc<AppState>, _user: UserSession, engine: &mut Engine) {
engine.register_fn("TIME", || -> Map {
let now = Local::now();
let mut map = Map::new();
map.insert("hour".into(), Dynamic::from(i64::from(now.hour())));
map.insert("minute".into(), Dynamic::from(i64::from(now.minute())));
map.insert("second".into(), Dynamic::from(i64::from(now.second())));
map.insert(
"formatted".into(),
Dynamic::from(now.format("%H:%M:%S").to_string()),
);
let is_pm = now.hour() >= 12;
map.insert("is_pm".into(), Dynamic::from(is_pm));
map.insert(
"ampm".into(),
Dynamic::from(if is_pm { "PM" } else { "AM" }.to_string()),
);
let hour12 = if now.hour() == 0 {
12
} else if now.hour() > 12 {
now.hour() - 12
} else {
now.hour()
};
map.insert("hour12".into(), Dynamic::from(i64::from(hour12)));
map
});
engine.register_fn("time", || -> Map {
let now = Local::now();
let mut map = Map::new();
map.insert("hour".into(), Dynamic::from(i64::from(now.hour())));
map.insert("minute".into(), Dynamic::from(i64::from(now.minute())));
map.insert("second".into(), Dynamic::from(i64::from(now.second())));
map.insert(
"formatted".into(),
Dynamic::from(now.format("%H:%M:%S").to_string()),
);
map
});
engine.register_fn("TIME_STR", || -> String {
Local::now().format("%H:%M:%S").to_string()
});
engine.register_fn("TIMESTAMP", || -> i64 { Utc::now().timestamp() });
engine.register_fn("timestamp", || -> i64 { Utc::now().timestamp() });
debug!("Registered TIME keyword with .property access");
}
pub fn timestamp_keyword(_state: &Arc<AppState>, _user: UserSession, engine: &mut Engine) {
engine.register_fn("UNIX_TIMESTAMP", || -> i64 { Utc::now().timestamp() });
engine.register_fn("TIMESTAMP_MS", || -> i64 { Utc::now().timestamp_millis() });
debug!("Registered TIMESTAMP keyword");
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Local;
#[test]
fn test_create_datetime_map() {
let now = Local::now();
let map = create_datetime_map(now);
assert!(map.contains_key("year"));
assert!(map.contains_key("month"));
assert!(map.contains_key("day"));
assert!(map.contains_key("hour"));
assert!(map.contains_key("minute"));
assert!(map.contains_key("second"));
assert!(map.contains_key("weekday"));
assert!(map.contains_key("timestamp"));
assert!(map.contains_key("formatted"));
assert!(map.contains_key("is_weekend"));
assert!(map.contains_key("quarter"));
}
#[test]
fn test_year_extraction() {
let now = Local::now();
let map = create_datetime_map(now);
let year = map.get("year").unwrap().as_int().unwrap();
assert!(year >= 2024);
}
#[test]
fn test_month_range() {
let now = Local::now();
let map = create_datetime_map(now);
let month = map.get("month").unwrap().as_int().unwrap();
assert!((1..=12).contains(&month));
}
#[test]
fn test_hour12_range() {
let now = Local::now();
let map = create_datetime_map(now);
let hour12 = map.get("hour12").unwrap().as_int().unwrap();
assert!((1..=12).contains(&hour12));
}
#[test]
fn test_quarter_calculation() {
let now = Local::now();
let map = create_datetime_map(now);
let quarter = map.get("quarter").unwrap().as_int().unwrap();
assert!((1..=4).contains(&quarter));
}
}