use super::parse_rfc3339;
#[test]
fn the_two_shapes_libpod_really_sends_both_parse() {
assert_eq!(
parse_rfc3339("2026-05-07T17:41:42.866453985Z"),
Some(1_778_175_702)
);
assert_eq!(
parse_rfc3339("2026-08-02T19:58:45.39802971-05:00"),
Some(1_785_718_725)
);
}
#[test]
fn the_offset_moves_the_instant_the_right_way() {
let utc = parse_rfc3339("2026-01-01T12:00:00Z").unwrap();
let behind = parse_rfc3339("2026-01-01T12:00:00-05:00").unwrap();
let ahead = parse_rfc3339("2026-01-01T12:00:00+05:00").unwrap();
assert_eq!(behind - utc, 5 * 3600, "a negative offset is behind UTC");
assert_eq!(utc - ahead, 5 * 3600, "a positive offset is ahead of UTC");
assert_eq!(
parse_rfc3339("2026-01-01T12:00:00+05:30").unwrap(),
utc - (5 * 3600 + 30 * 60)
);
}
#[test]
fn format_local_round_trips_on_any_machine() {
for unix in [
0_i64,
1,
-1,
-86_400,
68_169_600, 951_782_400, 1_709_164_800, 1_735_689_599, 1_735_689_600, 1_785_718_245, 4_102_444_800, ] {
let rendered = super::format_local(unix);
let reparsed = reparse(&rendered)
.unwrap_or_else(|| panic!("could not reparse {rendered:?} (from {unix})"));
assert_eq!(reparsed, unix, "{rendered:?} did not round-trip");
}
}
fn reparse(rendered: &str) -> Option<i64> {
let normalised = match rendered.rsplit_once(' ') {
Some((instant, zone)) if zone.starts_with(['+', '-']) => format!("{instant}{zone}"),
_ => rendered.to_string(),
};
parse_rfc3339(&normalised)
}
#[test]
fn format_local_renders_a_fixed_width_shape() {
let rendered = super::format_local(1_785_718_245);
assert_eq!(
rendered.len(),
26,
"{rendered:?} is not the width the TIME column is sized for"
);
let (instant, zone) = rendered.rsplit_once(' ').expect("no zone in {rendered:?}");
assert_eq!(instant.len(), 19, "{instant:?}");
assert!(
zone == "Z" || (zone.len() == 6 && zone.starts_with(['+', '-']) && &zone[3..4] == ":"),
"{zone:?} is not Z or ±HH:MM"
);
}
#[test]
fn the_rendering_is_pinned_for_every_offset_shape() {
let t = 1_785_718_245; assert_eq!(
super::render_with_offset(t, Some(-5 * 3600)),
"2026-08-02 19:50:45 -05:00"
);
assert_eq!(
super::render_with_offset(t, Some(5 * 3600 + 30 * 60)),
"2026-08-03 06:20:45 +05:30"
);
assert_eq!(
super::render_with_offset(t, Some(0)),
"2026-08-03 00:50:45 +00:00"
);
assert_eq!(
super::render_with_offset(t, Some(-(9 * 3600 + 30 * 60))),
"2026-08-02 15:20:45 -09:30"
);
}
#[test]
fn an_unknown_offset_renders_utc_and_labels_it() {
assert_eq!(
super::render_with_offset(1_785_718_245, None),
"2026-08-03 00:50:45Z"
);
assert_eq!(super::render_with_offset(0, None), "1970-01-01 00:00:00Z");
}
#[test]
fn the_civil_rendering_is_pinned_to_known_instants() {
assert_eq!(super::format_civil(0), "1970-01-01 00:00:00");
assert_eq!(super::format_civil(1), "1970-01-01 00:00:01");
assert_eq!(super::format_civil(68_169_600), "1972-02-29 00:00:00");
assert_eq!(super::format_civil(68_256_000), "1972-03-01 00:00:00");
assert_eq!(super::format_civil(951_782_400), "2000-02-29 00:00:00");
assert_eq!(super::format_civil(1_735_689_599), "2024-12-31 23:59:59");
assert_eq!(super::format_civil(1_735_689_600), "2025-01-01 00:00:00");
assert_eq!(super::format_civil(1_785_718_245), "2026-08-03 00:50:45");
}
#[test]
fn the_civil_rendering_handles_dates_before_the_epoch() {
assert_eq!(super::format_civil(-1), "1969-12-31 23:59:59");
assert_eq!(super::format_civil(-86_400), "1969-12-31 00:00:00");
}
#[test]
fn dates_before_the_epoch_parse_negative() {
assert_eq!(parse_rfc3339("1969-12-31T23:59:59Z"), Some(-1));
assert_eq!(parse_rfc3339("1969-12-31T00:00:00Z"), Some(-86_400));
}
#[test]
fn impossible_dates_are_rejected() {
assert_eq!(parse_rfc3339("2026-02-30T00:00:00Z"), None);
assert_eq!(
parse_rfc3339("2026-02-29T00:00:00Z"),
None,
"2026 is not a leap year"
);
assert_eq!(parse_rfc3339("2026-04-31T00:00:00Z"), None);
assert_eq!(parse_rfc3339("2026-13-01T00:00:00Z"), None);
assert_eq!(parse_rfc3339("2026-00-01T00:00:00Z"), None);
assert_eq!(parse_rfc3339("2026-01-00T00:00:00Z"), None);
assert_eq!(parse_rfc3339("2026-01-01T24:00:00Z"), None);
assert_eq!(parse_rfc3339("2026-01-01T00:60:00Z"), None);
}
#[test]
fn the_leap_year_rule_is_the_whole_rule() {
assert!(parse_rfc3339("2024-02-29T00:00:00Z").is_some());
assert!(parse_rfc3339("2000-02-29T00:00:00Z").is_some());
assert!(parse_rfc3339("2100-02-29T00:00:00Z").is_none());
assert!(parse_rfc3339("1900-02-29T00:00:00Z").is_none());
}
#[test]
fn malformed_input_is_refused() {
for bad in [
"",
"not a timestamp",
"2026-05-07T17:41:42", "2026-05-07T17:41:42.", "2026-05-07T17:41:42.Z", "2026-05-07T17:41:42Zextra", "2026-05-07T17:41:42+05", "2026-05-07T17:41:42+0500", "2026-05-07T17:41:42+05:00:00", "2026-05-07T17:41:42+99:00", "2026-05-07T17:41:42+05:99", "20 6-05-07T17:41:42Z", "+026-05-07T17:41:42Z", "2026/05/07T17:41:42Z", "2026-05-07X17:41:42Z", "2026-05-07T17-41-42Z", ] {
assert_eq!(parse_rfc3339(bad), None, "{bad:?} should not parse");
}
}
#[test]
fn every_permitted_separator_is_accepted() {
let expected = parse_rfc3339("2026-05-07T17:41:42Z");
assert!(expected.is_some());
assert_eq!(parse_rfc3339("2026-05-07t17:41:42Z"), expected);
assert_eq!(parse_rfc3339("2026-05-07 17:41:42Z"), expected);
assert_eq!(parse_rfc3339("2026-05-07T17:41:42z"), expected);
}
#[test]
fn a_leap_second_is_accepted() {
let ordinary = parse_rfc3339("2016-12-31T23:59:59Z").unwrap();
assert_eq!(parse_rfc3339("2016-12-31T23:59:60Z"), Some(ordinary + 1));
}
#[test]
fn the_fractional_part_is_ignored_at_any_length() {
let whole = parse_rfc3339("2026-05-07T17:41:42Z");
assert_eq!(parse_rfc3339("2026-05-07T17:41:42.9Z"), whole);
assert_eq!(parse_rfc3339("2026-05-07T17:41:42.866453985Z"), whole);
assert_eq!(parse_rfc3339("2026-05-07T17:41:42.000000000000Z"), whole);
}