{"record":{"id":"379af1118bd7c1bd","repo":"nautechsystems/nautilus_trader","slug":"negative-timestamp-unix-timestamp-ns","errorCode":null,"errorMessage":"Negative timestamp: {unix_timestamp_ns}","messagePattern":"Negative timestamp: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/datetime.rs","lineNumber":521,"sourceCode":"\n    // Calculate the offset in days for closest weekday (Mon-Fri)\n    let offset = match current_weekday {\n        1..=5 => 0, // Monday to Friday, no adjustment needed\n        6 => 1,     // Saturday, adjust to previous Friday\n        _ => 2,     // Sunday, adjust to previous Friday\n    };\n    // Calculate last closest weekday\n    let last_closest = date.checked_sub(Span::new().days(offset))?;\n\n    // Convert to UNIX nanoseconds\n    let unix_timestamp_ns = last_closest\n        .at(0, 0, 0, 0)\n        .to_zoned(TimeZone::UTC)?\n        .timestamp()\n        .as_nanosecond();\n\n    let ns_u64 = u64::try_from(unix_timestamp_ns)\n        .map_err(|_| anyhow::anyhow!(\"Negative timestamp: {unix_timestamp_ns}\"))?;\n    Ok(UnixNanos::from(ns_u64))\n}\n\n/// Check whether the given UNIX nanoseconds timestamp is within the last 24 hours.\n///\n/// # Errors\n///\n/// Returns an error if the timestamp is invalid.\npub fn is_within_last_24_hours(timestamp_ns: UnixNanos) -> anyhow::Result<bool> {\n    // Use the time seam so the comparison is deterministic under\n    // `simulation` + `cfg(madsim)` and we avoid a wall-clock call that\n    // would otherwise bypass the DST contract.\n    let timestamp_ns = timestamp_ns.as_u64();\n    let now_ns = nanos_since_unix_epoch();\n\n    // Future timestamps are not within the last 24 hours\n    if timestamp_ns > now_ns {\n        return Ok(false);","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/datetime.rs#L503-L539","documentation":"After computing midnight-UTC of the adjusted weekday, last_weekday_nanos converts the signed nanosecond timestamp to u64 for UnixNanos; a negative value means the date falls before the UNIX epoch (1970-01-01), which UnixNanos cannot represent. The library throws it because UnixNanos is an unsigned u64 nanosecond count.","triggerScenarios":"Calling last_weekday_nanos with any date before 1970-01-01, e.g. birthdates, historical data anchors like (1969, 12, 31), or years far in the past such as (1900, 1, 15).","commonSituations":"Using the function for historical calendar computations rather than market timestamps; a year sign error (-2024 instead of 2024); migrating legacy datasets with pre-epoch dates into nautilus types.","solutions":["Ensure input dates are on or after 1970-01-01; clamp or reject earlier dates at the call site.","If pre-epoch timestamps are genuinely needed, use a signed timestamp type (jiff Timestamp / i64 nanos) instead of UnixNanos.","Check for accidental negative years caused by sign or argument-order mistakes."],"exampleFix":"// before\nlet ns = last_weekday_nanos(1969, 7, 20)?; // pre-epoch -> negative timestamp\n// after\ndebug_assert!(year >= 1970);\nlet ns = last_weekday_nanos(1970, 1, 2)?;","handlingStrategy":"validation","validationCode":"// Rust: reject pre-epoch dates before calling\nif year < 1970 { return Err(anyhow!(\"date {year} is before UNIX epoch\")); }","typeGuard":null,"tryCatchPattern":"let ns = last_weekday_nanos(year, month, day)\n    .with_context(|| format!(\"week day anchor for {year}-{month:02}-{day:02}\"))?;","preventionTips":["Remember UnixNanos is unsigned: everything must be >= 1970-01-01T00:00:00Z.","Check year sign when dates come from subtraction or negation."],"tags":["datetime","unix-epoch","overflow","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}