fix: preserve fractional seconds in non-ISO date parsing#124
Conversation
These tests document the bug where strptime silently drops fractional seconds for non-ISO date formats (e.g., "15 Jan 2024 10:30:45.5"). The time regex consumed the ".frac" portion but did not capture it. Tests cover ISO 8601, day-month-year, RFC 2822-style, timezone abbreviations, AM/PM suffixes, and integer-only seconds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The time-of-day regex in strptime used a non-capturing group for the
fractional seconds portion: (?:\.\d+)?. This consumed the ".frac"
text but never assigned it to $frac, silently truncating sub-second
precision for all non-ISO date formats.
Changed to a capturing group (?:\.(\d+))? and updated the subsequent
group references ($5→$6 for zone marker, $6→$7 for AM/PM).
Before: str2time("15 Jan 2024 10:30:45.5 UTC") → 1705314645.000
After: str2time("15 Jan 2024 10:30:45.5 UTC") → 1705314645.500
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR fixes a silent data-loss bug where the time-of-day regex in Confidence Score: 5/5Safe to merge — minimal, targeted one-character regex change with correct group-reference updates and comprehensive tests. The change is surgical: one capture group added, three No files require special attention.
|
| Filename | Overview |
|---|---|
| lib/Date/Parse.pm | Adds one capture group to the time-of-day regex ((?:\.(\d+))?) and increments the three downstream $N references by 1 to correctly populate $frac for non-ISO date strings. |
| t/frac-seconds.t | New test file with 8 cases covering ISO 8601 (already worked), day-month-year (the bug), RFC 2822-style, timezone abbreviation, AM/PM, and integer-only seconds regression check. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["strptime(dtstr)"] --> B{ISO compact YYYYMMDDTHHMMSS?}
B -- yes --> C["Set hh,mm,ss,frac from capture groups (already captured .frac)"]
B -- no --> D{ISO with delimiter YYYY-MM-DD?}
D -- yes --> C
D -- no --> E{Boost-style YYYY-Mon-DD?}
E -- yes --> C
C --> F{hh defined?}
F -- yes --> G
E -- no --> F
F -- no --> H["Time-of-day regex [:\\s](hh):(mm)(:ss(?:\\.frac)?)?"]
H -- "matched (FIXED) captures frac into $5; $6=z; $7=ap" --> I["Set hh,mm,ss,frac; $zone if $6; $merid if $7"]
I --> G
H -- no match --> G["Parse date components year/month/day/zone"]
G --> J["ss += '0.' + frac if frac defined"]
J --> K["Return ss,mm,hh,day,month,year,zone,century"]
Reviews (1): Last reviewed commit: "fix: preserve fractional seconds in non-..." | Re-trigger Greptile
What
Fractional seconds are now preserved when parsing non-ISO date formats.
Why
The time-of-day regex in
strptimeconsumed the fractional seconds text (.5,.123, etc.) but used a non-capturing group, so the value was silently discarded. Only ISO 8601 formats preserved sub-second precision.This meant
str2time("15 Jan 2024 10:30:45.5 UTC")returned1705314645.000instead of1705314645.500— a quiet data loss that affects any caller relying on sub-second accuracy with non-ISO dates.How
Changed
(?:\.\d+)?to(?:\.(\d+))?in the time parsing regex (one character:\d+→(\d+)), and updated the three subsequent capture group references ($5→$6,$6→$7) that shifted as a result.Testing
8 new tests covering ISO 8601, day-month-year, RFC 2822-style, timezone abbreviations, AM/PM suffixes, and integer-only seconds. Full suite passes (1228 tests).
🤖 Generated with Claude Code
Quality Report
Changes: 2 files changed, 57 insertions(+), 4 deletions(-)
Code scan: clean
Tests: skipped
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline