Skip to content

Parsing a leap second timestamp can make it sort before a non-leap second timestamp #642

Description

@avsaase

When parsing a Timestamp from an RFC3339 timestamp that is a leap second, the second component of 60 gets replaced with 59 instead of clamping the timestamp to the last nanosecond of second 59. This can change the ordering of the Timestamp relative to one in the second before it.

use jiff::Timestamp;

fn main() {
    let a: Timestamp = "1998-12-31T23:59:59.2Z".parse().unwrap(); // a = 1998-12-31T23:59:59.2Z
    let b: Timestamp = "1998-12-31T23:59:60.1Z".parse().unwrap(); // b = 1998-12-31T23:59:59.1Z

    println!("a = {a}");
    println!("b = {b}");

    assert!(
        b > a,
        "leap-second timestamp sorted before an earlier-second timestamp"
    );
}

playground

The documentation does mention the clamping of the second component but it doesn't say how the nanosecond component is handled. The example also doesn't show this so it's not clear to me if this is intentional or not but it found it really surprising.

The only reason I see why this would be desirable is because clamping to the last nanosecond introduces additional precision that was not in the input. But for code working with timestamps this doesn't really seems like a problem to me. Parsing and formatting a leap second doesn't round-trip anyway so if you're parsing them you're bound to get some surprises regardless. IMO it's more important to stay as close as possible to the input value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions