windjammer_runtime/
time.rs1use chrono::{DateTime, Local, Utc};
6use std::time::Instant as StdInstant;
7
8pub use chrono::Duration;
10
11#[derive(Debug, Clone, Copy)]
13pub struct Instant {
14 inner: StdInstant,
15}
16
17impl Instant {
18 pub fn duration_since(&self, earlier: &Instant) -> Duration {
20 let elapsed = self.inner.duration_since(earlier.inner);
21 Duration::from_std(elapsed).unwrap_or_else(|_| Duration::zero())
22 }
23}
24
25pub fn now() -> Instant {
27 Instant {
28 inner: StdInstant::now(),
29 }
30}
31
32pub fn timestamp() -> i64 {
34 Utc::now().timestamp()
35}
36
37pub fn now_millis() -> i64 {
39 Utc::now().timestamp_millis()
40}
41
42pub fn now_string() -> String {
44 Utc::now().to_rfc3339()
45}
46
47pub fn now_local() -> String {
49 Local::now().to_rfc3339()
50}
51
52pub fn parse(s: &str) -> Result<i64, String> {
54 s.parse::<DateTime<Utc>>()
55 .map(|dt| dt.timestamp())
56 .map_err(|e| e.to_string())
57}
58
59pub fn parse_format(s: &str, fmt: &str) -> Result<i64, String> {
61 DateTime::parse_from_str(s, fmt)
62 .map(|dt| dt.timestamp())
63 .map_err(|e| e.to_string())
64}
65
66pub fn format(timestamp: i64, format: &str) -> String {
68 DateTime::from_timestamp(timestamp, 0)
69 .unwrap_or_else(Utc::now)
70 .format(format)
71 .to_string()
72}
73
74pub fn sleep(secs: u64) {
76 std::thread::sleep(std::time::Duration::from_secs(secs));
77}
78
79pub fn sleep_millis(millis: u64) {
81 std::thread::sleep(std::time::Duration::from_millis(millis));
82}
83
84pub fn add_seconds(timestamp: i64, seconds: i64) -> i64 {
86 DateTime::from_timestamp(timestamp, 0)
87 .and_then(|dt| dt.checked_add_signed(Duration::seconds(seconds)))
88 .map(|dt| dt.timestamp())
89 .unwrap_or(timestamp)
90}
91
92pub fn add_days(timestamp: i64, days: i64) -> i64 {
94 DateTime::from_timestamp(timestamp, 0)
95 .and_then(|dt| dt.checked_add_signed(Duration::days(days)))
96 .map(|dt| dt.timestamp())
97 .unwrap_or(timestamp)
98}
99
100pub fn duration_secs(start: i64, end: i64) -> i64 {
102 end - start
103}
104
105pub fn duration_millis(start: i64, end: i64) -> i64 {
107 (end - start) * 1000
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_now() {
116 let ts = timestamp();
117 assert!(ts > 1_600_000_000); }
119
120 #[test]
121 fn test_now_string() {
122 let s = now_string();
123 assert!(s.contains('T')); assert!(s.contains('Z') || s.contains('+'));
126 }
127
128 #[test]
129 fn test_parse() {
130 let result = parse("2024-01-01T00:00:00Z");
131 assert!(result.is_ok());
132 }
133
134 #[test]
135 fn test_add_seconds() {
136 let ts = 1_700_000_000i64;
137 let new_ts = add_seconds(ts, 3600);
138 assert_eq!(new_ts, ts + 3600);
139 }
140
141 #[test]
142 fn test_add_days() {
143 let ts = 1_700_000_000i64;
144 let new_ts = add_days(ts, 1);
145 assert_eq!(new_ts, ts + 86400);
146 }
147}