{"record":{"id":"1fb28cc91e0ad7ac","repo":"GitoxideLabs/gitoxide","slug":"day-lies-out-of-range","errorCode":null,"errorMessage":"Day {} lies out of range","messagePattern":"Day (.+?) lies out of range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-date/src/parse/relative.rs","lineNumber":174,"sourceCode":"                year: zdt.year(),\n                month: zdt.month(),\n                day: zdt.day(),\n                time: zdt.time(),\n                timezone: zdt.time_zone().clone(),\n            }\n        }\n    }\n\n    impl Fields {\n        /// Turn the fields back into a point in time: a day beyond the end of the month rolls over into the\n        /// following month. One month before May 31st is thus May 1st, a day after April 30th.\n        fn normalize(&self) -> Result<Zoned, Exn<Error>> {\n            let first_of_month = civil::Date::new(self.year, self.month, 1)\n                .or_raise(|| Error::new(format!(\"Date lies out of range: {}-{:02}\", self.year, self.month)))?;\n            let days_beyond_first = SignedDuration::from_secs((i64::from(self.day) - 1) * 24 * 60 * 60);\n            first_of_month\n                .checked_add(days_beyond_first)\n                .or_raise(|| Error::new(format!(\"Day {} lies out of range\", self.day)))?\n                .to_datetime(self.time)\n                .to_zoned(self.timezone.clone())\n                .or_raise(|| Error::new(\"Could not convert date to a point in time\"))\n        }\n    }\n\n    let now = now.ok_or(ValidationError::new(\"Missing current time\"))?;\n    let mut fields = Fields::from(now);\n    for Pair { period, count, unit } in pairs {\n        let err = || Error::new(format!(\"Couldn't parse span from '{period} {count}'\"));\n        match unit {\n            Unit::Seconds(factor) => {\n                let seconds = count\n                    .checked_mul(*factor)\n                    .map(SignedDuration::from_secs)\n                    .ok_or_else(err)?;\n                let ts = fields.normalize()?.timestamp().checked_sub(seconds).or_raise(err)?;\n                fields = ts.to_zoned(fields.timezone.clone()).into();","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-date/src/parse/relative.rs#L156-L192","documentation":"`Fields::normalize()` converts the day offset into a 24h-second `SignedDuration` and adds it to the first-of-month date via `checked_add`. When the addition overflows jiff's `civil::Date` range (the day field is so large/small that the resulting date leaves the supported range), `or_raise` attaches Error 'Day {day} lies out of range'.","triggerScenarios":"Relative-date parsing where a computed `day` value (from adding/subtracting large counts of months/weeks/days in `subtract_pairs`) pushes the date past the representable civil-date range, e.g. '100000 months ago'.","commonSituations":"Extreme relative date expressions in CLI tools or config like `--since='1000000 days ago'` implemented with gix-date.","solutions":["Bound the day/period magnitude before parsing so the resulting date stays within jiff's supported range","Catch the Error and surface a clearer 'date out of supported range' message to the user","Use absolute dates for very large offsets"],"exampleFix":"// before\nparse(\"now\", \"1000000 days ago\")\n// after\nlet days = count.min(365_000); // keep within representable range\nparse(\"now\", &format!(\"{days} days ago\"))","handlingStrategy":"validation","validationCode":"fn day_offset_safe(days: i64) -> bool {\n    days.abs() < 365 * 9000 // stays within jiff's civil-date range\n}","typeGuard":null,"tryCatchPattern":"match Fields::normalize(&fields) {\n    Ok(z) => z,\n    Err(e) => fallback_to_now_or_error(e),\n}","preventionTips":["Cap day/month/week counts before subtraction","Prefer absolute timestamps for extreme offsets","Add range tests for large relative dates"],"tags":["date","parsing","overflow"],"backgroundTag":"value-out-of-range","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}