1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ExplainResult {
10 pub rule_name: String,
12 pub rule_version: Option<String>,
14 pub rule_tags: Vec<String>,
16 pub logic_snapshot: Value,
18 pub context_snapshot: Value,
20 pub result: Value,
22 pub evaluated_at: String,
24 pub engine: String,
26}
27
28impl ExplainResult {
29 pub(crate) fn new(
30 rule_name: String,
31 rule_version: Option<String>,
32 rule_tags: Vec<String>,
33 logic_snapshot: Value,
34 context_snapshot: Value,
35 result: Value,
36 ) -> Self {
37 Self {
38 rule_name,
39 rule_version,
40 rule_tags,
41 logic_snapshot,
42 context_snapshot,
43 result,
44 evaluated_at: chrono_like_now(),
45 engine: format!("tempus-engine@{}", env!("CARGO_PKG_VERSION")),
46 }
47 }
48}
49
50fn chrono_like_now() -> String {
53 use std::time::{SystemTime, UNIX_EPOCH};
55 let secs = SystemTime::now()
56 .duration_since(UNIX_EPOCH)
57 .map(|d| d.as_secs())
58 .unwrap_or(0);
59 let s = secs % 60;
61 let m = (secs / 60) % 60;
62 let h = (secs / 3600) % 24;
63 let days = secs / 86400;
64 let year = 1970 + days / 365;
66 let day_of_year = days % 365;
67 let month = day_of_year / 30 + 1;
68 let day = day_of_year % 30 + 1;
69 format!(
70 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
71 year, month, day, h, m, s
72 )
73}