Skip to content

fix: preserve fractional seconds in non-ISO date parsing#124

Merged
atoomic merged 2 commits into
cpan-authors:mainfrom
Koan-Bot:koan.atoomic/fix-fractional-seconds-non-iso
Apr 26, 2026
Merged

fix: preserve fractional seconds in non-ISO date parsing#124
atoomic merged 2 commits into
cpan-authors:mainfrom
Koan-Bot:koan.atoomic/fix-fractional-seconds-non-iso

Conversation

@Koan-Bot

@Koan-Bot Koan-Bot commented Apr 25, 2026

Copy link
Copy Markdown

What

Fractional seconds are now preserved when parsing non-ISO date formats.

Why

The time-of-day regex in strptime consumed 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") returned 1705314645.000 instead of 1705314645.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

Koan-Bot and others added 2 commits April 25, 2026 06:26
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>
@atoomic atoomic marked this pull request as ready for review April 26, 2026 12:23
@atoomic atoomic merged commit 05d3fbc into cpan-authors:main Apr 26, 2026
22 checks passed
@greptile-apps

greptile-apps Bot commented Apr 26, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a silent data-loss bug where the time-of-day regex in strptime consumed fractional seconds (.5, .123, etc.) via a non-capturing group, discarding them for all non-ISO date formats. The one-character change — adding a capture group to produce (?:\.(\d+))? — correctly captures the digits, and the three subsequent $N back-references ($5$6, $6$7) are shifted consistently. The $frac variable was already declared in scope and the $ss += "0.$frac" accumulation at line 217 already existed, so the fix slots in cleanly. Eight new tests verify the fix across common format variants.

Confidence Score: 5/5

Safe 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 $N references incremented by 1, no new variables introduced, and the pre-existing $frac accumulation path at line 217 handles the value correctly. Regex trace confirms group numbering is exact. Eight new tests cover all impacted format paths. No regressions to pre-existing ISO behavior.

No files require special attention.

Important Files Changed

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"]
Loading

Reviews (1): Last reviewed commit: "fix: preserve fractional seconds in non-..." | Re-trigger Greptile

@Koan-Bot Koan-Bot deleted the koan.atoomic/fix-fractional-seconds-non-iso branch April 27, 2026 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants