Skip to content

About

Small, unsafe-free Rust port of upstream tzcode asctime.c — the legacy fixed-format time formatter, verified byte-for-byte against a compiled asctime.c oracle. Not a libc/general formatter.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

asctime-rs

A small, unsafe-free Rust port of upstream tzcode asctime.c — the legacy fixed-format time formatter (Wed Jun 30 21:49:08 1993\n), provided as the asctime library crate.

let tm = asctime::Tm { tm_sec: 8, tm_min: 49, tm_hour: 21, tm_mday: 30,
    tm_mon: 5, tm_year: 93, tm_wday: 3 };
assert_eq!(asctime::asctime(&tm).unwrap(), "Wed Jun 30 21:49:08 1993\n");

Claim boundary

asctime-rs does not replace libc, does not implement a general date/time formatting framework, and does not define civil-time truth. It ports the observable legacy formatting behaviour of upstream tzcode asctime.c into Rust and verifies output against the compiled upstream C oracle for admitted tm rows. It preserves the constant, locale-independent legacy format — it is not a better date formatter, a strftime subset, a chrono/jiff helper, or a locale-aware formatter. It is the legacy fixed-format member of the Rust tzdb runtime toolchain, beside localtime-rs and strftime-rs.

API

pub struct Tm { tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday: i32 }
pub fn asctime(tm: &Tm) -> Result<String, Error>;            // the classic call (big buffer)
pub fn asctime_r(tm: &Tm, bufsize: usize) -> Result<String, Error>; // buffer-bounded (EOVERFLOW)
pub const STD_ASCTIME_BUF_SIZE: usize = 26;

Fields are used verbatim (no normalization), exactly as asctime.c reads them: out-of-range tm_wday/tm_mon → "???"; years −999..9999 use %04ld, beyond that five spaces + %ld (the vintage-newline padding); %.2d keeps the sign outside the two-digit magnitude; %3d space-pads the day. asctime never overflows for any i32 tm (the buffer is sized for it); asctime_r with a small buffer returns Err(Overflow) (C's EOVERFLOW).

Oracle & evidence

The oracle is a C harness linking upstream asctime.c, fed explicit struct tm rows, printing asctime()'s output.

  • Sweep: 132 / 132 byte-identical — all weekday/month indices (+ out-of-range), day-of-month spacing (1/9/10/31/100/−5/extreme), year-width branches (year 1, 900, −100, 10000, ±extreme), leap-second tm_sec=60, out-of-range time fields, and a 60000-day spread of realistic dates. Receipt: reports/asctime-oracle/.
  • Kani: the weekday/month name-table index is proven in bounds.
  • Fuzz: cargo +nightly fuzz run asc over arbitrary tm fields × buffer sizes — 8.8M executions, 0 crashes.

Build & test

cargo test
cargo clippy --all-targets -- -D warnings
cargo kani --harness name_index_in_bounds
python3 lab/oracle/sweep.py        # needs the compiled asctime.c harness

License

BSD-3-Clause, retaining the upstream tz copyright (asctime.c is public domain / BSD-licensed in the tz distribution). An independent reimplementation.

About

Small, unsafe-free Rust port of upstream tzcode asctime.c — the legacy fixed-format time formatter, verified byte-for-byte against a compiled asctime.c oracle. Not a libc/general formatter.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages