agent_doc_core/
log_time.rs1pub fn format_log_timestamp(secs: u64) -> String {
27 let days = (secs / 86_400) as i64;
28 let tod = secs % 86_400;
29 let (hh, mm, ss) = (tod / 3_600, (tod % 3_600) / 60, tod % 60);
30
31 let z = days + 719_468;
33 let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
34 let doe = (z - era * 146_097) as u64; let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365; let y = yoe as i64 + era * 400;
37 let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); let mp = (5 * doy + 2) / 153; let d = doy - (153 * mp + 2) / 5 + 1; let m = if mp < 10 { mp + 3 } else { mp - 9 }; let year = if m <= 2 { y + 1 } else { y };
42
43 format!("{year:04}-{m:02}-{d:02}T{hh:02}:{mm:02}:{ss:02}Z")
44}
45
46pub fn parse_log_timestamp(raw: &str) -> Option<u64> {
51 let s = raw.trim();
52 if let Ok(epoch) = s.parse::<u64>() {
53 return Some(epoch);
54 }
55 let s = s.strip_suffix('Z').unwrap_or(s);
56 let (date, time) = s.split_once('T')?;
57 let mut dp = date.split('-');
58 let year: i64 = dp.next()?.parse().ok()?;
59 let month: u64 = dp.next()?.parse().ok()?;
60 let day: u64 = dp.next()?.parse().ok()?;
61 if dp.next().is_some() || !(1..=12).contains(&month) || !(1..=31).contains(&day) {
62 return None;
63 }
64 let mut tp = time.split(':');
65 let hh: u64 = tp.next()?.parse().ok()?;
66 let mm: u64 = tp.next()?.parse().ok()?;
67 let ss: u64 = tp.next()?.parse().ok()?;
68 if tp.next().is_some() || hh > 23 || mm > 59 || ss > 60 {
69 return None;
70 }
71
72 let y = if month <= 2 { year - 1 } else { year };
74 let era = if y >= 0 { y } else { y - 399 } / 400;
75 let yoe = (y - era * 400) as u64; let mp = if month > 2 { month - 3 } else { month + 9 }; let doy = (153 * mp + 2) / 5 + day - 1; let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; let days = era * 146_097 + doe as i64 - 719_468;
80 let secs = days * 86_400 + (hh * 3_600 + mm * 60 + ss) as i64;
81 u64::try_from(secs).ok()
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn format_matches_known_iso8601_utc() {
90 assert_eq!(format_log_timestamp(1_781_771_180), "2026-06-18T08:26:20Z");
92 assert_eq!(format_log_timestamp(0), "1970-01-01T00:00:00Z");
93 assert_eq!(format_log_timestamp(1_709_164_800), "2024-02-29T00:00:00Z");
94 }
95
96 #[test]
97 fn parse_accepts_epoch_and_iso_and_round_trips() {
98 assert_eq!(parse_log_timestamp("1781771180"), Some(1_781_771_180));
100 assert_eq!(
102 parse_log_timestamp("2026-06-18T08:26:20Z"),
103 Some(1_781_771_180)
104 );
105 for secs in [0_u64, 1, 1_709_164_800, 1_781_915_847, 4_102_444_800] {
107 assert_eq!(
108 parse_log_timestamp(&format_log_timestamp(secs)),
109 Some(secs),
110 "round-trip failed for epoch {secs}"
111 );
112 }
113 assert_eq!(parse_log_timestamp("not-a-timestamp"), None);
115 assert_eq!(parse_log_timestamp("2026-13-01T00:00:00Z"), None);
116 }
117}