ruby/ruby · error · ArgumentError
yday #{yday} out of range
Error message
yday #{yday} out of range What it means
When Date._parse recognizes an ordinal-date component (:yday), make_time validates it against 1..366 before doing any calendar math. A day-of-year outside that window (0, negative, or >366) raises ArgumentError 'yday N out of range' immediately.
Source
Thrown at lib/time.rb:214
end
return year, mon, day, hour, min, sec
end
private :apply_offset
def make_time(date, year, yday, mon, day, hour, min, sec, sec_fraction, zone, now)
if !year && !yday && !mon && !day && !hour && !min && !sec && !sec_fraction
raise ArgumentError, "no time information in #{date.inspect}"
end
off = nil
if year || now
off_year = year || now.year
off = zone_offset(zone, off_year) if zone
end
if yday
unless (1..366) === yday
raise ArgumentError, "yday #{yday} out of range"
end
mon, day = (yday-1).divmod(31)
mon += 1
day += 1
t = make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
diff = yday - t.yday
return t if diff.zero?
day += diff
if day > 28 and day > (mday = month_days(off_year, mon))
if (mon += 1) > 12
raise ArgumentError, "yday #{yday} out of range"
end
day -= mday
end
return make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
end
if now and now.respond_to?(:getlocal)View on GitHub (pinned to 0e5b888e1c)
Solutions
- Validate before parsing: yday must be in 1..366 (1..365 for non-leap years)
- Build ordinal dates with the standard API: Date.ordinal(year, yday).to_time instead of string round-trips
- Clamp or reject the value at the producer that generates the string
- Rescue ArgumentError and report the offending record id
Example fix
# before
t = Time.parse("2021-400") # raises: yday 400 out of range
# after
raise ArgumentError, "bad yday #{doy}" unless (1..366).cover?(doy)
t = Date.ordinal(2021, doy)&.to_time Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, "yday #{doy} out of range" unless (1..366).cover?(doy)
t = Date.ordinal(year, doy).to_time Try / catch
begin Time.parse(ordinal_str) rescue ArgumentError quarantine(record) # log the bad ordinal date and move on end
Prevention
- Validate day-of-year at ingestion: 1..366, tighter for non-leap years
- Generate ordinal dates with Date.ordinal, never string interpolation
- Add a max-DDD sanity check in exporters
When it happens
Trigger: Time.parse("2021-400"); Time.parse("2021-0"); strings like "21-367" where the parser reads a day-of-year; exporting tools that emit DDD without clamping.
Common situations: Malformed ordinal dates from data exports or industrial loggers (YYYY-DDD format); user-typed day-of-year treated as 0-based; hand-rolled date arithmetic producing yday 0 or 367+.
Related errors
- no time information in #{date.inspect}
- invalid date or strptime format - '#{date}' '#{format}'
- timezone argument given as positional and keyword arguments
- end of file reached
- OpenSSL::PKey::DH is immutable on OpenSSL 3.0; use OpenSSL::
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/830d3523368ee6d1.
Report an issue: GitHub.