pharos_runtime_core/
time.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3pub fn current_timestamp_utc() -> String {
5 let seconds = SystemTime::now()
6 .duration_since(UNIX_EPOCH)
7 .unwrap_or_default()
8 .as_secs();
9 timestamp_from_epoch_seconds(seconds)
10}
11
12pub fn timestamp_after_seconds_utc(additional_seconds: u64) -> String {
14 let seconds = SystemTime::now()
15 .duration_since(UNIX_EPOCH)
16 .unwrap_or_default()
17 .as_secs()
18 .saturating_add(additional_seconds);
19 timestamp_from_epoch_seconds(seconds)
20}
21
22pub fn timestamp_from_epoch_seconds(seconds: u64) -> String {
24 const SECONDS_PER_DAY: u64 = 86_400;
25 let days = seconds / SECONDS_PER_DAY;
26 let seconds_of_day = seconds % SECONDS_PER_DAY;
27 let hour = seconds_of_day / 3600;
28 let minute = (seconds_of_day % 3600) / 60;
29 let second = seconds_of_day % 60;
30
31 let z = days as i64 + 719_468;
32 let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
33 let doe = z - era * 146_097;
34 let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
35 let y = yoe + era * 400;
36 let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
37 let mp = (5 * doy + 2) / 153;
38 let day = doy - (153 * mp + 2) / 5 + 1;
39 let month = mp + if mp < 10 { 3 } else { -9 };
40 let year = y + if month <= 2 { 1 } else { 0 };
41
42 format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}Z")
43}
44
45#[cfg(test)]
46mod tests {
47 use super::timestamp_from_epoch_seconds;
48
49 #[test]
50 fn formats_unix_epoch_as_utc_timestamp() {
51 assert_eq!(timestamp_from_epoch_seconds(0), "1970-01-01T00:00:00Z");
52 }
53
54 #[test]
55 fn formats_known_utc_timestamp() {
56 assert_eq!(
57 timestamp_from_epoch_seconds(1_700_000_000),
58 "2023-11-14T22:13:20Z"
59 );
60 }
61}