Skip to content

fix: align Date::Language::str2time year handling with Date::Parse#138

Draft
Koan-Bot wants to merge 1 commit intocpan-authors:mainfrom
Koan-Bot:koan.atoomic/fix-language-str2time-year-normalization
Draft

fix: align Date::Language::str2time year handling with Date::Parse#138
Koan-Bot wants to merge 1 commit intocpan-authors:mainfrom
Koan-Bot:koan.atoomic/fix-language-str2time-year-normalization

Conversation

@Koan-Bot
Copy link
Copy Markdown

@Koan-Bot Koan-Bot commented May 6, 2026

What

Adds missing year normalization to Date::Language::str2time so it
produces the same results as Date::Parse::str2time for two-digit years.

Why

Date::Language::str2time delegated two-digit year interpretation entirely
to Time::Local, whose sliding-window algorithm diverges from the fixed
POSIX threshold that Date::Parse::str2time applies. On modern
Time::Local (>= 1.28), years 69–76 resolve to the 2000s via Language
but the 1900s via Parse — e.g., "1 Jun 69 GMT" gives 2069 vs 1969.

Users switching between the two APIs (Parse for English, Language for
localized dates) would get different results for the same input string.

How

  • Capture $century from strptime return (8th element, previously ignored)
  • Restore 4-digit year when century is present ($year += 1900)
  • Apply POSIX two-digit year normalization (69–99 → 1900s, 00–68 → 2000s)
  • Separate fractional seconds before timegm and re-add to result

Testing

  • Extended t/lang-str2time.t with two-digit year consistency tests
    covering the full range (0, 1, 26, 50, 68, 69, 70, 75, 95, 99)
  • Added 4-digit year round-trip and fractional seconds preservation tests
  • Full suite passes (prove -l t/ — all tests green)

🤖 Generated with Claude Code


Quality Report

Changes: 2 files changed, 69 insertions(+), 2 deletions(-)

Code scan: clean

Tests: skipped

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

Date::Language::str2time was missing two pieces of year normalization
that Date::Parse::str2time applies:

1. Century restoration — when strptime returns a $century value (from
   4-digit year input), the year must be restored via $year += 1900.
   Without this, Language.pm relied on Time::Local treating small
   values as years-since-1900, which works but is fragile.

2. Two-digit year POSIX normalization — Date::Parse uses a fixed
   threshold (69-99 → 1900s, 00-68 → 2000s) matching POSIX strptime
   conventions. Language.pm delegated this to Time::Local's sliding
   window, which on Time::Local >= 1.28 centers on the current year,
   producing different results for years 69-76 (e.g., "1 Jun 69"
   resolves to 2069 via Language but 1969 via Parse).

Also adds explicit fractional-second handling ($frac separation and
re-addition) to match Date::Parse::str2time's approach, instead of
relying on Time::Local accepting float seconds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant