Skip to main content

tzcompile/model/
leap.rs

1//! The leap-second table model (T11) — **a distinct time model, not a transition stream.**
2//!
3//! ## Invariant (do not let this bleed into ordinary-zone code)
4//!
5//! Leap seconds are **not** local-time-type transitions:
6//! * they do not select an abbreviation,
7//! * they do not change `isdst`,
8//! * they only contribute to the TZif **leap-second correction table**.
9//!
10//! These types are deliberately separate from [`crate::tzif::Transition`] /
11//! [`crate::tzif::LocalTimeType`] so the distinction is visible in code. They are parsed *only* from
12//! an explicit leap-source file (see [`crate::source::parse_leap_source`]); the ordinary `tzdata.zi`
13//! zone-source path never produces them.
14
15/// One leap-second table entry.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct LeapSecond {
18    /// The leap instant **as written**, in seconds since the 1970 epoch. For a `Stationary` leap this
19    /// is the UT instant; for a `Rolling` leap it is the *local-wall* instant — the offset conversion
20    /// is a later (T11.4) emission concern, so the value is stored verbatim with `rolling` recorded.
21    pub trans: i64,
22    /// Per-line correction: `+1` or `-1`. (Reference `zic` accumulates these into a *cumulative*
23    /// table at emission via `adjleap`; that is an emission concern, not done here.)
24    pub correction: i32,
25    /// `true` = `Rolling` (local-wall instant), `false` = `Stationary` (UT instant).
26    pub rolling: bool,
27}
28
29/// A parsed leap-second table: the entries plus an optional table-expiry instant.
30#[derive(Debug, Clone, Default, PartialEq, Eq)]
31pub struct LeapTable {
32    /// Leap entries, kept **sorted by `trans`** (insertion-sorted, mirroring `zic`'s `leapadd`).
33    pub entries: Vec<LeapSecond>,
34    /// The `Expires` instant (seconds since 1970), if any. At most one `Expires` line is permitted
35    /// (a second is a parse error, matching reference `zic`).
36    pub expires: Option<i64>,
37}