Skip to main content

epoch_seconds

Function epoch_seconds 

Source
pub fn epoch_seconds(ts: &str) -> Option<i64>
Expand description

The inverse of rfc3339: 2026-08-29T10:40:00Z back to Unix seconds.

It lives beside the formatter because the two are one thing, and a repository that had the one without the other grew a second parser every time somebody needed to compare two recorded instants. Strict about the shape it accepts — exactly YYYY-MM-DDTHH:MM:SSZ, which is the only shape this tool writes — because a lenient parser that guessed at a half-recognised string would answer None for a malformed timestamp and a plausible number for a different one, and only the first of those is safe.

None is the honest answer for anything else, and the caller’s job is to report it as unjudgeable rather than as fresh: an episode whose evidence cannot be read as a time is one a recovery sweep must skip and count, never one it may sweep.

use majordomus_cli::peers::{epoch_seconds, rfc3339};
use std::time::{Duration, UNIX_EPOCH};

assert_eq!(epoch_seconds("1970-01-01T00:00:00Z"), Some(0));
assert_eq!(epoch_seconds("2026-08-29T10:40:00Z"), Some(1_788_000_000));
assert_eq!(epoch_seconds("not a timestamp"), None);
assert_eq!(epoch_seconds("2026-08-29 10:40:00Z"), None, "the T is not optional");
assert_eq!(epoch_seconds("2026-08-29T10:40:00+02:00"), None, "UTC or nothing");

// and it round-trips with the formatter it is the inverse of
for secs in [0u64, 1, 1_788_000_000, 2_000_000_000] {
    let text = rfc3339(UNIX_EPOCH + Duration::from_secs(secs));
    assert_eq!(epoch_seconds(&text), Some(secs as i64), "{text}");
}