fusabi_stdlib_ext/
time.rs1use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7use fusabi_host::ExecutionContext;
8use fusabi_host::Value;
9
10pub fn now(
12 _args: &[Value],
13 _ctx: &ExecutionContext,
14) -> fusabi_host::Result<Value> {
15 let timestamp = SystemTime::now()
16 .duration_since(UNIX_EPOCH)
17 .map(|d| d.as_secs())
18 .unwrap_or(0);
19
20 Ok(Value::Int(timestamp as i64))
21}
22
23pub fn now_millis(
25 _args: &[Value],
26 _ctx: &ExecutionContext,
27) -> fusabi_host::Result<Value> {
28 let timestamp = SystemTime::now()
29 .duration_since(UNIX_EPOCH)
30 .map(|d| d.as_millis())
31 .unwrap_or(0);
32
33 Ok(Value::Int(timestamp as i64))
34}
35
36pub fn sleep(
38 args: &[Value],
39 _ctx: &ExecutionContext,
40) -> fusabi_host::Result<Value> {
41 let millis = args
42 .first()
43 .and_then(|v| v.as_int())
44 .ok_or_else(|| fusabi_host::Error::host_function("time.sleep: missing milliseconds argument"))?;
45
46 if millis < 0 {
47 return Err(fusabi_host::Error::host_function("time.sleep: milliseconds must be non-negative"));
48 }
49
50 std::thread::sleep(Duration::from_millis(millis as u64));
51 Ok(Value::Null)
52}
53
54pub fn format_time(
56 args: &[Value],
57 _ctx: &ExecutionContext,
58) -> fusabi_host::Result<Value> {
59 let timestamp = args
60 .first()
61 .and_then(|v| v.as_int())
62 .ok_or_else(|| fusabi_host::Error::host_function("time.format: missing timestamp argument"))?;
63
64 let format_str = args
65 .get(1)
66 .and_then(|v| v.as_str())
67 .unwrap_or("%Y-%m-%d %H:%M:%S");
68
69 let formatted = format_timestamp(timestamp, format_str);
71 Ok(Value::String(formatted))
72}
73
74pub fn parse_time(
76 args: &[Value],
77 _ctx: &ExecutionContext,
78) -> fusabi_host::Result<Value> {
79 let time_str = args
80 .first()
81 .and_then(|v| v.as_str())
82 .ok_or_else(|| fusabi_host::Error::host_function("time.parse: missing time string argument"))?;
83
84 let _format_str = args
85 .get(1)
86 .and_then(|v| v.as_str())
87 .unwrap_or("%Y-%m-%d %H:%M:%S");
88
89 Err(fusabi_host::Error::host_function(format!(
92 "time.parse: parsing '{}' not yet implemented",
93 time_str
94 )))
95}
96
97fn format_timestamp(timestamp: i64, _format: &str) -> String {
99 let secs = timestamp as u64;
101 let days = secs / 86400;
102 let hours = (secs % 86400) / 3600;
103 let minutes = (secs % 3600) / 60;
104 let seconds = secs % 60;
105
106 let years = 1970 + (days / 365);
108 let remaining_days = days % 365;
109 let month = remaining_days / 30 + 1;
110 let day = remaining_days % 30 + 1;
111
112 format!(
113 "{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
114 years, month, day, hours, minutes, seconds
115 )
116}
117
118pub mod duration {
120 pub fn seconds_to_millis(secs: i64) -> i64 {
122 secs * 1000
123 }
124
125 pub fn millis_to_seconds(millis: i64) -> i64 {
127 millis / 1000
128 }
129
130 pub fn minutes_to_seconds(mins: i64) -> i64 {
132 mins * 60
133 }
134
135 pub fn hours_to_seconds(hours: i64) -> i64 {
137 hours * 3600
138 }
139
140 pub fn days_to_seconds(days: i64) -> i64 {
142 days * 86400
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use fusabi_host::Capabilities;
150 use fusabi_host::{Sandbox, SandboxConfig};
151 use fusabi_host::Limits;
152
153 fn create_test_ctx() -> ExecutionContext {
154 let sandbox = Sandbox::new(SandboxConfig::default()).unwrap();
155 ExecutionContext::new(1, Capabilities::none(), Limits::default(), sandbox)
156 }
157
158 #[test]
159 fn test_now() {
160 let ctx = create_test_ctx();
161 let result = now(&[], &ctx).unwrap();
162
163 let timestamp = result.as_int().unwrap();
164 assert!(timestamp > 0);
165 assert!(timestamp > 1700000000); }
167
168 #[test]
169 fn test_now_millis() {
170 let ctx = create_test_ctx();
171 let result = now_millis(&[], &ctx).unwrap();
172
173 let timestamp = result.as_int().unwrap();
174 assert!(timestamp > 0);
175 assert!(timestamp > 1700000000000); }
177
178 #[test]
179 fn test_format_time() {
180 let ctx = create_test_ctx();
181
182 let result = format_time(&[Value::Int(1704067200)], &ctx).unwrap();
184 let formatted = result.as_str().unwrap();
185
186 assert!(formatted.contains("2024"));
187 }
188
189 #[test]
190 fn test_sleep_validation() {
191 let ctx = create_test_ctx();
192
193 let result = sleep(&[Value::Int(-100)], &ctx);
195 assert!(result.is_err());
196 }
197
198 #[test]
199 fn test_duration_helpers() {
200 assert_eq!(duration::seconds_to_millis(5), 5000);
201 assert_eq!(duration::millis_to_seconds(5000), 5);
202 assert_eq!(duration::minutes_to_seconds(2), 120);
203 assert_eq!(duration::hours_to_seconds(1), 3600);
204 assert_eq!(duration::days_to_seconds(1), 86400);
205 }
206}