{"record":{"id":"270c8575d03c49a9","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-execution-timestamp-time-str","errorCode":null,"errorMessage":"Failed to parse execution timestamp '{time_str}': {e}","messagePattern":"Failed to parse execution timestamp '(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/execution/parse.rs","lineNumber":402,"sourceCode":"/// Timezones are resolved through Jiff's bundled IANA tz database, so any\n/// region abbreviation or name that IB stamps the execution with (e.g. `MET`,\n/// `EST`, `America/New_York`) is honored, matching the v1 pandas-based parser.\n/// This matters because some IB accounts (e.g. European paper accounts) report a\n/// server timezone such as `MET` that the gateway cannot be coerced out of.\n///\n/// # Errors\n///\n/// Returns an error if the timestamp is malformed, the timezone is\n/// unrecognized, or the local time is non-existent (a DST spring-forward gap).\n/// DST fall-back folds resolve to the earliest matching instant.\npub fn parse_execution_time(time_str: &str) -> anyhow::Result<UnixNanos> {\n    const NAIVE_FORMAT: &str = \"%Y%m%d %H:%M:%S\";\n\n    // Hyphenated, space-less form (e.g. \"20250225-15:15:00\") is always UTC.\n    if !time_str.contains(' ') {\n        let normalized = time_str.replace('-', \" \");\n        let dt = DateTime::strptime(NAIVE_FORMAT, &normalized).map_err(|e| {\n            anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\")\n        })?;\n        return datetime_to_unix_nanos(Offset::UTC.to_timestamp(dt)?, time_str);\n    }\n\n    // Split into at most three parts: date, time, and optional timezone token.\n    // The timezone token itself never contains a space, so `splitn(3, ' ')`\n    // correctly groups IANA names such as \"America/New_York\".\n    let mut parts = time_str.splitn(3, ' ');\n    let (Some(date), Some(time)) = (parts.next(), parts.next()) else {\n        anyhow::bail!(\"Invalid execution time format: {time_str}\");\n    };\n    let tz_str = parts.next().unwrap_or(\"\").trim();\n\n    let naive_str = format!(\"{date} {time}\");\n    let dt = DateTime::strptime(NAIVE_FORMAT, &naive_str)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\"))?;\n\n    let utc = if tz_str.is_empty() {","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/execution/parse.rs#L384-L420","documentation":"parse_execution_time converts IB execution timestamps into Unix nanos. For the hyphenated, space-less form (e.g. \"20250225-15:15:00\", always UTC), it normalizes the string and parses with the fixed format \"%Y%m%d %H:%M:%S\". If the string doesn't match that format (wrong ordering, missing seconds, alphabetic garbage), the strptime fails and this error is thrown.","triggerScenarios":"Called from parse_historical_fill_report, handle_execution_data, build_pending_combo_fill, or generate_leg_fill with a time_str containing no space but not matching %Y%m%d-%H:%M:%S — e.g. \"2025-02-25 15:15:00\", \"20250225 15:15\", or empty string.","commonSituations":"Custom IB time format settings in TWS/Gateway; API version differences in the execution report format; timestamps from report files edited or reformatted by other tooling.","solutions":["Inspect the offending time_str (it is included in the message) and compare against expected IB formats like 20250225, 15:15:00 or 20250225-15:15:00.","Reset the date/time format settings in TWS / IB Gateway API configuration to the default.","Upgrade the ibapi crate / adapter if your IB API version emits a new timestamp format, or pre-normalize the string before passing it on."],"exampleFix":"// before\nlet dt = DateTime::strptime(NAIVE_FORMAT, &normalized).map_err(|e| {\n    anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\")\n})?;\n// after\nlet normalized = time_str\n    .replace('-', \" \")\n    .replace('T', \" \");\nlet dt = DateTime::strptime(NAIVE_FORMAT, &normalized).map_err(|e| {\n    anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\")\n})?;","handlingStrategy":"validation","validationCode":"// Rust: validate the hyphenated IB timestamp before parsing\nfn looks_like_ib_hyphenated(s: &str) -> bool {\n    let b = s.as_bytes();\n    b.len() == 19\n        && b[8] == b'-'\n        && b.iter().enumerate().all(|(i, c)| {\n            i == 8 || c.is_ascii_digit() || i == 13 || i == 16 || c == b':' == false\n        })\n}","typeGuard":"fn is_valid_execution_time(time_str: &str) -> bool {\n    time_str.len() == 19 || (time_str.len() >= 17 && time_str.contains(' '))\n}","tryCatchPattern":"match parse_execution_time(time_str) {\n    Ok(nanos) => nanos,\n    Err(e) => {\n        tracing::error!(\"Skipping execution record with bad timestamp: {e}\");\n        return Ok(());\n    }\n}","preventionTips":["Keep TWS / IB Gateway date-time format settings at defaults","Validate timestamp shape in message normalization before the adapter","Log raw execution rows so malformed timestamps are diagnosable"],"tags":["timestamp","parsing","date-format","interactive-brokers","rust"],"backgroundTag":"invalid-date-format","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"}