Skip to main content

pharos_runtime_core/
time.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2
3/// Returns the current UTC timestamp in Pharos runtime text format.
4pub 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
12/// Returns the current UTC timestamp plus a bounded number of seconds.
13pub 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
22/// Formats an epoch-second value as the Pharos UTC timestamp string.
23pub 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}