GitoxideLabs/gitoxide · error
Day lies out of range
Error message
Day {} lies out of range What it means
`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'.
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
Example fix
// before
parse("now", "1000000 days ago")
// after
let days = count.min(365_000); // keep within representable range
parse("now", &format!("{days} days ago")) Defensive patterns
Strategy: validation
Validate before calling
fn day_offset_safe(days: i64) -> bool {
days.abs() < 365 * 9000 // stays within jiff's civil-date range
} Try / catch
match Fields::normalize(&fields) {
Ok(z) => z,
Err(e) => fallback_to_now_or_error(e),
} Prevention
- Cap day/month/week counts before subtraction
- Prefer absolute timestamps for extreme offsets
- Add range tests for large relative dates
When it happens
Trigger: 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'.
Common situations: Extreme relative date expressions in CLI tools or config like `--since='1000000 days ago'` implemented with gix-date.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Couldn't parse span from
- Failed to subtract from
- Date lies out of range
- cannot find character that we didn't search for
- (re-raised revision-spec parse error via bail!(err))
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/1fb28cc91e0ad7ac.
Report an issue: GitHub.
Appendix: source
Thrown at gix-date/src/parse/relative.rs:174
year: zdt.year(),
month: zdt.month(),
day: zdt.day(),
time: zdt.time(),
timezone: zdt.time_zone().clone(),
}
}
}
impl Fields {
/// Turn the fields back into a point in time: a day beyond the end of the month rolls over into the
/// following month. One month before May 31st is thus May 1st, a day after April 30th.
fn normalize(&self) -> Result<Zoned, Exn<Error>> {
let first_of_month = civil::Date::new(self.year, self.month, 1)
.or_raise(|| Error::new(format!("Date lies out of range: {}-{:02}", self.year, self.month)))?;
let days_beyond_first = SignedDuration::from_secs((i64::from(self.day) - 1) * 24 * 60 * 60);
first_of_month
.checked_add(days_beyond_first)
.or_raise(|| Error::new(format!("Day {} lies out of range", self.day)))?
.to_datetime(self.time)
.to_zoned(self.timezone.clone())
.or_raise(|| Error::new("Could not convert date to a point in time"))
}
}
let now = now.ok_or(ValidationError::new("Missing current time"))?;
let mut fields = Fields::from(now);
for Pair { period, count, unit } in pairs {
let err = || Error::new(format!("Couldn't parse span from '{period} {count}'"));
match unit {
Unit::Seconds(factor) => {
let seconds = count
.checked_mul(*factor)
.map(SignedDuration::from_secs)
.ok_or_else(err)?;
let ts = fields.normalize()?.timestamp().checked_sub(seconds).or_raise(err)?;
fields = ts.to_zoned(fields.timezone.clone()).into();View on GitHub (pinned to e73179060b)