{"record":{"id":"830c91ce85a03a93","repo":"pola-rs/polars","slug":"invalid-time","errorCode":null,"errorMessage":"invalid time","messagePattern":"invalid time","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-arrow/src/temporal_conversions.rs","lineNumber":73,"sourceCode":"\n/// converts a `i64` representing a `date64` to [`NaiveDateTime`]\n#[inline]\npub fn date64_to_datetime(v: i64) -> NaiveDateTime {\n    TimeDelta::try_milliseconds(v)\n        .and_then(|delta| unix_epoch().checked_add_signed(delta))\n        .expect(\"invalid or out-of-range datetime\")\n}\n\n/// converts a `i64` representing a `date64` to [`NaiveDate`]\n#[inline]\npub fn date64_to_date(milliseconds: i64) -> NaiveDate {\n    date64_to_datetime(milliseconds).date()\n}\n\n/// converts a `i32` representing a `time32(s)` to [`NaiveTime`]\n#[inline]\npub fn time32s_to_time(v: i32) -> NaiveTime {\n    NaiveTime::from_num_seconds_from_midnight_opt(v as u32, 0).expect(\"invalid time\")\n}\n\n/// converts a `i64` representing a `duration(s)` to [`Duration`]\n#[inline]\npub fn duration_s_to_duration(v: i64) -> Duration {\n    Duration::try_seconds(v).expect(\"out-of-range duration\")\n}\n\n/// converts a `i64` representing a `duration(ms)` to [`Duration`]\n#[inline]\npub fn duration_ms_to_duration(v: i64) -> Duration {\n    Duration::try_milliseconds(v).expect(\"out-of-range in duration conversion\")\n}\n\n/// converts a `i64` representing a `duration(us)` to [`Duration`]\n#[inline]\npub fn duration_us_to_duration(v: i64) -> Duration {\n    Duration::microseconds(v)","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/crates/polars-arrow/src/temporal_conversions.rs#L55-L91","documentation":"Panics inside time32s_to_time: the i32 seconds value is cast with 'v as u32', so any negative value wraps to a huge u32, and NaiveTime::from_num_seconds_from_midnight_opt requires seconds < 86400. Any v < 0 or v >= 86400 therefore fails the .expect('invalid time').","triggerScenarios":"Converting a time32(s) array containing negative values (sentinels, misparsed data) or values >= 86400 (overflow from unit mismatch, e.g. milliseconds stored in a seconds column).","commonSituations":"CSVs with '-1' defaults in time columns; ms-epoch-of-day values written into a time32(s) field; corrupt arrow data.","solutions":["Range-check first: accept only 0 <= v < 86_400","Null out or clamp invalid values before conversion","Fix the unit mismatch upstream (ms vs s)","Where possible use the Polars cast layer with strict=False to emit nulls"],"exampleFix":"// before\nlet t = time32s_to_time(v); // panics for v < 0 or v >= 86_400\n\n// after\nlet t = (0..86_400).contains(&v)\n    .then(|| time32s_to_time(v))\n    .unwrap_or(NaiveTime::MIN); // or propagate null","handlingStrategy":"validation","validationCode":"fn time32s_valid(v: i32) -> bool {\n    (0..86_400).contains(&v) // seconds within one day\n}","typeGuard":"fn is_valid_time32s(v: i32) -> bool {\n    (0..86_400).contains(&v)\n}","tryCatchPattern":null,"preventionTips":["Remember time32(s) must be 0..=86399; negatives wrap when cast to u32 and panic","Reject or null -1 sentinels in time-of-day columns before conversion","Verify seconds vs milliseconds units with the producer","Filter invalid values at load time rather than deep in display logic"],"tags":["rust","polars","arrow","temporal","time","panic"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}