Search by

aegisora / date-format-rule

Date Format Rule provides a simple, rule-based date/time format validation implementation for the Aegisora ecosystem

Maintainers

Package info

github.com/Aegisora/date-format-rule

Language:Shell

pkg:composer/aegisora/date-format-rule

Transparency log

Statistics

Installs: 39

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-31 16:48 UTC

This package is auto-updated.

Last update: 2026-08-31 16:52:33 UTC


README

Latest Version Total Downloads Code Coverage Badge Software License PHPStan Badge

Date Format Rule provides a simple, rule-based date/time format validation implementation for the Aegisora ecosystem.

It is built on top of aegisora/rule-contract and follows its strict validation architecture, ensuring consistent and predictable behavior across applications.

This rule is useful for validating user input, form fields, birth dates, appointment times, API request parameters, imported data, and any other string that must conform to a specific date/time format.

๐Ÿ“‘ Table of Contents

โœจ Features

  • ๐Ÿ”น Lightweight and dependency-free except aegisora/rule-contract
  • ๐Ÿ”น Validates a string against any PHP date/time format (Y-m-d, d/m/Y H:i, H:i:s, ...)
  • ๐Ÿ”น Supports the full PHP format syntax, including escaped literals (\T)
  • ๐Ÿ”น Exhaustive check โ€” rejects overflow dates (2026-02-31), out-of-range values, and non-canonical input the parser silently tolerates
  • ๐Ÿ”น Optional time zone support
  • ๐Ÿ”น Rejects non-string input as an invalid context
  • ๐Ÿ”น Fully compatible with Aegisora validation pipeline
  • ๐Ÿ”น Strict Context โ†’ Result validation flow
  • ๐Ÿ”น No raw booleans โ€” only structured results
  • ๐Ÿ”น Safe execution via base Rule abstraction
  • ๐Ÿ”น Ready to use out of the box

๐Ÿ“ฆ Installation

composer require aegisora/date-format-rule

๐Ÿš€ Core Concept

This package implements a single validation rule:

  • accepts a string value via Context
  • checks whether the string is a valid date/time that strictly matches the configured format
  • returns a standardized Result

Under the hood it wraps the common โ€” and easy to get wrong โ€” boilerplate:

$date = DateTimeImmutable::createFromFormat('!' . $format, $value);
$errors = DateTimeImmutable::getLastErrors();
// $date !== false, no warnings/errors, and $date->format($format) === $value

into a reusable rule that reports its outcome through a Result object instead of a raw boolean.

๐Ÿ—๏ธ Basic Usage

use Aegisora\RuleContract\Models\Context;
use Aegisora\Rules\DateFormatRule;

$result = (new DateFormatRule('Y-m-d'))->validate(Context::create('2026-08-31'));

if ($result->isValid()) {
    // value is a valid date in the given format
} else {
    // value does not match the format
}

โœ… Valid vs Invalid

The rule passes when the string is a real date/time that renders back exactly as the input under the configured format, and fails otherwise.

Dates

(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-08-31')); // valid   โ€” a real calendar date
(new DateFormatRule('Y-m-d'))->validate(Context::create('2024-02-29')); // valid   โ€” 2024 is a leap year

(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-02-31')); // invalid โ€” February has no 31st
(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-02-29')); // invalid โ€” 2026 is not a leap year
(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-13-01')); // invalid โ€” month out of range

Strict formatting

(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-8-3'));         // invalid โ€” missing leading zeros
(new DateFormatRule('Y-m-d'))->validate(Context::create('2026/08/31'));       // invalid โ€” wrong separator
(new DateFormatRule('Y-m-d'))->validate(Context::create('2026-08-31 extra')); // invalid โ€” trailing garbage

(new DateFormatRule('Y-n-j'))->validate(Context::create('2026-8-3'));         // valid   โ€” the format allows no leading zeros

Times and combined formats

(new DateFormatRule('H:i'))->validate(Context::create('14:30'));      // valid
(new DateFormatRule('H:i:s'))->validate(Context::create('24:00:00')); // invalid โ€” hour out of range

(new DateFormatRule('d F Y'))->validate(Context::create('31 August 2026'));             // valid โ€” textual month
(new DateFormatRule('Y-m-d\TH:i:s'))->validate(Context::create('2026-08-31T10:20:30')); // valid โ€” escaped literal T

๐Ÿงช Validation Result

If the string is a valid date/time matching the format, the rule returns a valid result.

$result->isValid(); // true

If the string does not match the format, the rule returns an invalid result.

$result->isValid(); // false
$result->getFailedRuleCode(); // date_format_rule

If the context value is not a string, the rule throws:

Aegisora\RuleContract\Exceptions\InvalidRuleContextException

If the configured format is an empty string, the rule throws:

Aegisora\RuleContract\Exceptions\InvalidRuleContextException

๐ŸŒ Time Zones

An optional DateTimeZone can be passed as the second argument. It is used while parsing the value, which matters for formats that carry time information.

use Aegisora\RuleContract\Models\Context;
use Aegisora\Rules\DateFormatRule;
use DateTimeZone;

$rule = new DateFormatRule('Y-m-d H:i:s', new DateTimeZone('Europe/Moscow'));

$rule->validate(Context::create('2026-08-31 12:00:00')); // valid

If the format itself carries a time zone (e, T, P, O), that value takes precedence and the argument is ignored.

๐Ÿ”— Guardian Usage

This rule can be used together with aegisora/guardian to build fluent validation pipelines.

use Aegisora\Guardian\Guardian;
use Aegisora\Rules\DateFormatRule;
use App\Exceptions\InvalidBirthDateException;

$guardian = new Guardian();

$guardian
    ->that($birthDate)
    ->must(new DateFormatRule('Y-m-d'), new InvalidBirthDateException())
    ->validate();

If the value does not match the format, Guardian throws the provided domain exception.

๐Ÿงญ Real-World Examples

Date Format Rule is useful for enforcing date/time constraints before values are persisted or processed.

Examples

User Registration:

require a birth date in ISO format (Y-m-d)
Scheduling:

ensure an appointment time matches H:i and represents a real time of day
Imports:

reject CSV rows whose date column is not a real calendar date
API:

reject request parameters that do not match the expected date/time shape

๐Ÿงฉ Constructor & API

new DateFormatRule($format);

  • creates a rule that passes when the value is a valid date/time strictly matching the PHP $format

new DateFormatRule($format, $timeZone);

  • additionally applies the given DateTimeZone while parsing the value

(new DateFormatRule($format))->validate($context);

  • $context โ€” Context wrapping the string value to validate

๐Ÿ›๏ธ Architecture

This package relies on aegisora/rule-contract.

Flow:

  1. validate() is called
  2. Context is passed in
  3. The configured format is checked; an empty format raises InvalidRuleContextException
  4. The string value is extracted from context (non-strings raise InvalidRuleContextException)
  5. The value is parsed with DateTimeImmutable::createFromFormat(), checked against getLastErrors() for overflow/out-of-range warnings, and round-tripped back through the format to reject non-canonical input
  6. Result is returned โ€” valid on a strict match, invalid with the date_format_rule code otherwise

All logic is safely handled by Rule contract.

โš–๏ธ License

This package is open-source and licensed under the MIT License. See the LICENSE for details.

๐ŸŒฑ Contributing

Contributions are welcome and greatly appreciated! See the CONTRIBUTING for details.

๐ŸŒŸ Support

If you find this project useful, please consider giving it a star on GitHub!

It helps the project grow and motivates further development.