Skip to content

[WIP] Let a clock decide what "now" means during a validation - #1834

Draft
alganet wants to merge 1 commit into
mainfrom
feat/psr20-clock
Draft

[WIP] Let a clock decide what "now" means during a validation#1834
alganet wants to merge 1 commit into
mainfrom
feat/psr20-clock

Conversation

@alganet

@alganet alganet commented Aug 16, 2026

Copy link
Copy Markdown
Member

A value the user gives is rarely a complete instant. "3 days ago" counts back from now, "10:00" means today at ten, a format without a year borrows the current one, and a comparison against "18 years ago" has to work out when that was. PHP completes each of those from the system clock, which it reads afresh every time, so no two values in the same validation are measured from quite the same moment. A value sitting exactly on a boundary then falls to whichever side the microseconds landed on: "7 years ago" counts as six years, because it is resolved a moment after the time it is measured against was read, and the count of years rounds the shortfall down.

Introduce a PSR-20 clock, taken by every validator that needs to know the time: DateTimeDiff, the comparisons, Between, DateTime, LeapDate, LeapYear and Time. The clock is read where PHP read the system one and no more often, so a system clock, which is what a validator falls back to and what the container names by default, answers exactly as before, six years included.

Name FrozenClock in the container instead and every chain builds one for itself, hands it to the validators it creates, attributes included, and holds it still while the validation runs, taking the time again on the next run so that a chain kept around never reports a stale one. Every validator of a chain then agrees on what "now" is, and "7 years ago" becomes the seven years it says it is.

CanResolveDateTime completes a value the way PHP does, asking the clock where PHP asks the system: never for a value naming a full calendar date, and otherwise only once the value has been parsed. Validators receive the clock as the parameter they declare, so the fluent API is untouched, generated mixins and documented signatures included.

@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.22%. Comparing base (d2f78a0) to head (082a90d).

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1834      +/-   ##
============================================
+ Coverage     97.12%   97.22%   +0.10%     
- Complexity     1069     1105      +36     
============================================
  Files           198      199       +1     
  Lines          2505     2597      +92     
============================================
+ Hits           2433     2525      +92     
  Misses           72       72              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

A value the user gives is rarely a complete instant. "3 days ago" counts
back from now, "10:00" means today at ten, a format without a year
borrows the current one, and a comparison against "18 years ago" has to
work out when that was. PHP completes each of those from the system
clock, which it reads afresh every time, so no two values in the same
validation are measured from quite the same moment. A value sitting
exactly on a boundary then falls to whichever side the microseconds
landed on: "7 years ago" counts as six years, because it is resolved a
moment after the time it is measured against was read, and the count of
years rounds the shortfall down.

Introduce a PSR-20 clock, taken by every validator that needs to know
the time: DateTimeDiff, the comparisons, Between, DateTime, LeapDate,
LeapYear and Time. The clock is read where PHP read the system one and
no more often, so a system clock, which is what a validator falls back
to and what the container names by default, answers exactly as before,
six years included.

Name FrozenClock in the container instead and every chain builds one for
itself, hands it to the validators it creates, attributes included, and
holds it still while the validation runs, taking the time again on the
next run so that a chain kept around never reports a stale one. Every
validator of a chain then agrees on what "now" is, and "7 years ago"
becomes the seven years it says it is.

CanResolveDateTime completes a value the way PHP does, asking the clock
where PHP asks the system: never for a value naming a full calendar
date, and otherwise only once the value has been parsed. Validators
receive the clock as the parameter they declare, so the fluent API is
untouched, generated mixins and documented signatures included.
@alganet alganet changed the title Let a clock decide what "now" means during a validation [WIP] Let a clock decide what "now" means during a validation Aug 16, 2026
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