Skip to main content

time/
time.rs

1//! Working with timestamps and durations in CEL.
2//!
3//! Run with: cargo run -p cel-core --example time
4
5use cel_core::{CelType, Duration, Env, MapActivation, Timestamp};
6
7fn main() {
8    println!("=== CEL Timestamp and Duration Examples ===\n");
9
10    // Create an environment with the standard library
11    let env = Env::with_standard_library()
12        .with_variable("event_time", CelType::Timestamp)
13        .with_variable("timeout", CelType::Duration)
14        .with_variable("deadline", CelType::Timestamp);
15
16    // -------------------------------------------------------------------------
17    // 1. Creating timestamps and durations from strings
18    // -------------------------------------------------------------------------
19    println!("1. Parsing timestamps and durations from strings:");
20
21    // Parse a timestamp from an RFC 3339 string
22    let ast = env.compile("timestamp('2024-03-15T10:30:00Z')").unwrap();
23    let program = env.program(&ast).unwrap();
24    let result = program.eval(&MapActivation::new());
25    println!("   timestamp('2024-03-15T10:30:00Z') = {}", result);
26
27    // Parse a duration string
28    let ast = env.compile("duration('1h30m')").unwrap();
29    let program = env.program(&ast).unwrap();
30    let result = program.eval(&MapActivation::new());
31    println!("   duration('1h30m') = {}", result);
32
33    // Various duration formats
34    for expr in [
35        "duration('30s')",
36        "duration('500ms')",
37        "duration('2h30m45s')",
38        "duration('-1h')",
39    ] {
40        let ast = env.compile(expr).unwrap();
41        let program = env.program(&ast).unwrap();
42        let result = program.eval(&MapActivation::new());
43        println!("   {} = {}", expr, result);
44    }
45
46    // -------------------------------------------------------------------------
47    // 2. Timestamp arithmetic
48    // -------------------------------------------------------------------------
49    println!("\n2. Timestamp arithmetic:");
50
51    let mut activation = MapActivation::new();
52    activation.insert("event_time", Timestamp::new(1710498600, 0)); // 2024-03-15T10:30:00Z
53    activation.insert("timeout", Duration::new(3600, 0)); // 1 hour
54
55    // Add duration to timestamp
56    let ast = env.compile("event_time + timeout").unwrap();
57    let program = env.program(&ast).unwrap();
58    let result = program.eval(&activation);
59    println!("   event_time + timeout = {}", result);
60
61    // Subtract duration from timestamp
62    let ast = env.compile("event_time - duration('30m')").unwrap();
63    let program = env.program(&ast).unwrap();
64    let result = program.eval(&activation);
65    println!("   event_time - duration('30m') = {}", result);
66
67    // Difference between two timestamps yields a duration
68    activation.insert("deadline", Timestamp::new(1710505800, 0)); // 2024-03-15T12:30:00Z
69    let ast = env.compile("deadline - event_time").unwrap();
70    let program = env.program(&ast).unwrap();
71    let result = program.eval(&activation);
72    println!("   deadline - event_time = {}", result);
73
74    // -------------------------------------------------------------------------
75    // 3. Timestamp comparisons
76    // -------------------------------------------------------------------------
77    println!("\n3. Timestamp comparisons:");
78
79    let ast = env.compile("event_time < deadline").unwrap();
80    let program = env.program(&ast).unwrap();
81    let result = program.eval(&activation);
82    println!("   event_time < deadline = {}", result);
83
84    let ast = env
85        .compile("event_time + duration('3h') > deadline")
86        .unwrap();
87    let program = env.program(&ast).unwrap();
88    let result = program.eval(&activation);
89    println!("   event_time + duration('3h') > deadline = {}", result);
90
91    // -------------------------------------------------------------------------
92    // 4. Timestamp accessors (UTC)
93    // -------------------------------------------------------------------------
94    println!("\n4. Timestamp accessors (UTC):");
95
96    let accessors = [
97        ("getFullYear", "event_time.getFullYear()"),
98        ("getMonth (0-11)", "event_time.getMonth()"),
99        ("getDate (1-31)", "event_time.getDate()"),
100        ("getDayOfWeek (0=Sun)", "event_time.getDayOfWeek()"),
101        ("getDayOfYear (0-365)", "event_time.getDayOfYear()"),
102        ("getHours", "event_time.getHours()"),
103        ("getMinutes", "event_time.getMinutes()"),
104        ("getSeconds", "event_time.getSeconds()"),
105    ];
106
107    for (name, expr) in accessors {
108        let ast = env.compile(expr).unwrap();
109        let program = env.program(&ast).unwrap();
110        let result = program.eval(&activation);
111        println!("   {} = {}", name, result);
112    }
113
114    // -------------------------------------------------------------------------
115    // 5. Timestamp accessors with timezone
116    // -------------------------------------------------------------------------
117    println!("\n5. Timestamp accessors with timezone:");
118
119    // Same timestamp in different timezones
120    let timezones = [
121        ("UTC", "event_time.getHours()"),
122        (
123            "America/New_York",
124            "event_time.getHours('America/New_York')",
125        ),
126        ("Europe/London", "event_time.getHours('Europe/London')"),
127        ("Asia/Tokyo", "event_time.getHours('Asia/Tokyo')"),
128        ("+05:30 (India)", "event_time.getHours('+05:30')"),
129    ];
130
131    for (tz_name, expr) in timezones {
132        let ast = env.compile(expr).unwrap();
133        let program = env.program(&ast).unwrap();
134        let result = program.eval(&activation);
135        println!("   Hours in {} = {}", tz_name, result);
136    }
137
138    // -------------------------------------------------------------------------
139    // 6. Duration accessors
140    // -------------------------------------------------------------------------
141    println!("\n6. Duration accessors:");
142
143    let mut activation = MapActivation::new();
144    activation.insert("d", Duration::new(5400, 500_000_000)); // 1h30m + 500ms
145
146    let accessors = [
147        ("getHours (total)", "d.getHours()"),
148        ("getMinutes (total)", "d.getMinutes()"),
149        ("getSeconds (total)", "d.getSeconds()"),
150        ("getMilliseconds", "d.getMilliseconds()"),
151    ];
152
153    for (name, expr) in accessors {
154        let env = Env::with_standard_library().with_variable("d", CelType::Duration);
155        let ast = env.compile(expr).unwrap();
156        let program = env.program(&ast).unwrap();
157        let result = program.eval(&activation);
158        println!("   {} = {}", name, result);
159    }
160
161    // -------------------------------------------------------------------------
162    // 7. Converting to string
163    // -------------------------------------------------------------------------
164    println!("\n7. Converting to string:");
165
166    let mut activation = MapActivation::new();
167    activation.insert("ts", Timestamp::new(1710498600, 123000000)); // with nanos
168    activation.insert("d", Duration::new(5400, 500000000));
169
170    let env = Env::with_standard_library()
171        .with_variable("ts", CelType::Timestamp)
172        .with_variable("d", CelType::Duration);
173
174    let ast = env.compile("string(ts)").unwrap();
175    let program = env.program(&ast).unwrap();
176    let result = program.eval(&activation);
177    println!("   string(ts) = {}", result);
178
179    let ast = env.compile("string(d)").unwrap();
180    let program = env.program(&ast).unwrap();
181    let result = program.eval(&activation);
182    println!("   string(d) = {}", result);
183
184    // -------------------------------------------------------------------------
185    // 8. Practical example: deadline checking
186    // -------------------------------------------------------------------------
187    println!("\n8. Practical example - deadline checking:");
188
189    let env = Env::with_standard_library()
190        .with_variable("request_time", CelType::Timestamp)
191        .with_variable("max_response_time", CelType::Duration)
192        .with_variable("current_time", CelType::Timestamp);
193
194    let mut activation = MapActivation::new();
195    activation.insert("request_time", Timestamp::new(1710498600, 0));
196    activation.insert("max_response_time", Duration::new(30, 0)); // 30 seconds
197    activation.insert("current_time", Timestamp::new(1710498620, 0)); // 20 seconds later
198
199    let expr = "current_time < request_time + max_response_time";
200    let ast = env.compile(expr).unwrap();
201    let program = env.program(&ast).unwrap();
202    let result = program.eval(&activation);
203    println!(
204        "   Is response within deadline? (current < request + 30s) = {}",
205        result
206    );
207
208    // Simulate timeout
209    activation.insert("current_time", Timestamp::new(1710498640, 0)); // 40 seconds later
210    let result = program.eval(&activation);
211    println!("   Is response within deadline? (40s later) = {}", result);
212
213    // -------------------------------------------------------------------------
214    // 9. Creating timestamps from integers (Unix epoch seconds)
215    // -------------------------------------------------------------------------
216    println!("\n9. Creating timestamps from integers:");
217
218    let env = Env::with_standard_library();
219    let ast = env.compile("timestamp(1710498600)").unwrap();
220    let program = env.program(&ast).unwrap();
221    let result = program.eval(&MapActivation::new());
222    println!("   timestamp(1710498600) = {}", result);
223
224    // Convert timestamp to epoch seconds
225    let ast = env
226        .compile("int(timestamp('2024-03-15T10:30:00Z'))")
227        .unwrap();
228    let program = env.program(&ast).unwrap();
229    let result = program.eval(&MapActivation::new());
230    println!("   int(timestamp('2024-03-15T10:30:00Z')) = {}", result);
231
232    println!("\n=== Done ===");
233}