PSR-20 набор часов для PHP 8.1+: системные, замороженные, мок-, монотонные, со смещением, масштабом и усечением, шаговые и очередь; TimeSpan с наносекундной точностью, Stopwatch, Deadline, DatePoint и CalendarDate — календарная арифметика месяцев/лет с контролем переполнения и локализацией уровня Ca

Maintainers

Package info

gitverse.ru/cloud-castle/clock

Homepage

Issues

Documentation

pkg:composer/cloud-castle/clock

Transparency log

Statistics

Installs: 90

Dependents: 5

Suggesters: 0

v1.3.0 2026-07-30 11:08 UTC

README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle Clock

CloudCastle Clock

Packagist Version PHP Version License Downloads Monthly Downloads Packagist Stars Dependents

GitVerse Issues Releases CI

PHPStan Psalm PHPMD PHPCS Coverage Infection MSI OpenSSF Scorecard

PSR-20 часы для PHP 8.1+ с детерминированным временем в тестах: 9 реализаций часов (системные, замороженные, мок-, монотонные, со смещением, масштабом, усечением, шаговые, очередь), TimeSpan с наносекундной точностью, Stopwatch, Deadline, DatePoint и CalendarDate — календарная работа уровня Carbon с локализацией без ICU/ext-intl. Лёгкие зависимости: psr/clock и cloud-castle/inflector.

Установка

composer require cloud-castle/clock

Требуется PHP 8.1+.

Быстрый старт

<?php

use CloudCastle\Clock\CalendarDate;
use CloudCastle\Clock\Clock;
use CloudCastle\Clock\ClockHolder;
use CloudCastle\Clock\Deadline;
use CloudCastle\Clock\MockClock;
use CloudCastle\Clock\Stopwatch;
use CloudCastle\Clock\TimeSpan;

// Продакшн: системные часы в нужной зоне, внедряются как ClockInterface.
$clock = Clock::utc();
$moment = $clock->now();            // DateTimeImmutable
$unix = $clock->timestamp();        // int без создания объекта даты

// Тесты: мок-часы с виртуальным сном — retry/backoff за миллисекунды.
$mock = MockClock::from('2026-01-01 00:00:00', 'UTC');
$mock->sleep(30.0);                 // время сдвинулось, процесс не спал
$mock->advance(TimeSpan::ofMinutes(5)->seconds());

// Глобальные часы со скоуп-подменой: после колбэка всё как было.
ClockHolder::within($mock, function (): void {
    // Clock::now() внутри читает мок-часы.
});

// Длительности с наносекундной точностью.
$span = TimeSpan::fromString('1h 30m')->plus(TimeSpan::ofSeconds(15.5));
echo $span->toIso8601();            // PT1H30M15.5S

// Дедлайны, привязанные к часам.
$deadline = Deadline::after($clock, TimeSpan::ofSeconds(30));
if (!$deadline->isExpired()) {
    $left = $deadline->remaining(); // TimeSpan
}

// Секундомер на монотонном таймере — с кругами.
$watch = Stopwatch::start();
$watch->lap('подготовка');
$seconds = $watch->stop();

// Календарная работа уровня Carbon без ICU/ext-intl.
$date = CalendarDate::parse('2026-01-31', 'UTC');
echo $date->addMonthsNoOverflow(1)->format('Y-m-d');  // 2026-02-28 (не «3 марта»)
echo $date->subDays(9)->diffForHumans($date, 'ru');   // «9 дней назад» (склонение через inflector)

Возможности

  • 9 реализаций часов: SystemClock, FrozenClock, MockClock (виртуальный sleep()), MonotonicClock, OffsetClock, ScaledClock, TruncatingClock, StepClock, QueueClock + CallbackClock и адаптер PsrClockAdapter.
  • TimeSpan — длительность с наносекундной точностью: фабрики от наносекунд до недель, разбор ISO 8601 / 1h 30m / relative-строк PHP, точная арифметика с контролем переполнения.
  • Deadline — дедлайны с isExpired()/remaining(), детерминированные в тестах.
  • Stopwatch — монотонный секундомер с кругами и measure(callable).
  • DatePoint — моменты от часов приложения с типизированными ошибками.
  • CalendarDate — календарная работа уровня Carbon без ICU/ext-intl: арифметика месяцев/лет с контролем переполнения (addMonthsNoOverflow()), границы периодов/декады/века, предикаты (isWeekend(), isToday(), isLastOfMonth()), разницы (diffInDays()diffInYears()), навигация (next(), firstOfMonth()), fluent-сеттеры, форматтеры (toDateString(), ISO/RFC/ATOM/W3C), детерминированный парсинг относительных строк (parse('next friday') от часов приложения — без глобального setTestNow), локализованные названия и diffForHumans() на 6 языках (склонения — через cloud-castle/inflector, включая три славянские формы русского).
  • ClockHolder — глобальные часы с within() (скоуп-подмена с автовосстановлением).
  • Дешёвые примитивы timestamp()/microtime() без материализации объекта даты.

Полное описание каждой возможности — в wiki.

Сравнение с аналогами

Все таблицы ниже сгенерированы автоматически из честных сравнительных тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов, PHP 8.3.32, без Xdebug.

1. Функциональность

Возможность🏆 CloudCastlesymfonycarbonlcobuccibesteergebnisnew¹
PSR-20 ClockInterface (now(): DateTimeImmutable)
Замороженные часы для детерминизма тестов
Мок-часы с виртуальным sleep()
Монотонные часы (защита от прыжков системного времени)
Смещение времени декоратором (OffsetClock)
Масштаб времени декоратором (ScaledClock)
Усечение моментов до произвольной единицы
Value object длительности с наносекундной точностью
Дедлайны с остатком времени (Deadline)
Шаговые часы и часы-очередь для сценарных тестов
Секундомер с кругами в составе пакета
Дешёвые примитивы timestamp()/microtime() без объекта даты
Момент от часов приложения (DatePoint)
Скоуп-подмена глобальных часов с автовосстановлением
Адаптер произвольных PSR-20 часов
Календарная арифметика месяцев/лет с контролем переполнения (CalendarDate)
Локализованный diffForHumans и isoFormat без ext-intl
Календарные предикаты и разницы (isWeekend, diffInDays, next)
Всего🏆 18672320

2. Безопасность и корректность

Свойство🏆 CloudCastlesymfonycarbonlcobuccibesteergebnisnew¹
Иммутабельные показания (DateTimeImmutable)
Явная временная зона (не зависит от date.timezone)
Детерминизм тестов без обязательного глобального состояния
Монотонность (устойчивость к откату системных часов)
Типизированные исключения вместо false/warning на границе ввода
Санитайзинг враждебного ввода в сообщениях исключений
Контроль целочисленного переполнения длительностей
Минимальные зависимости (≤2, без ICU/ext-intl)
Всего🏆 8434342

3. Производительность: now()

Получение текущего момента now(), 200 000 раз (минимум из 6).

РешениеВремя (мс)Итог
new¹117,5базовый уровень (не библиотека)
🏆 lcobucci130,4быстрейшее среди библиотек
ergebnis132,9аналог
beste133аналог
CloudCastle138,7аналог
symfony181аналог
carbon806,1аналог

4. Производительность: unix-метка

Текущая unix-метка (целые секунды), 200 000 раз.

РешениеВремя (мс)Итог
new¹21базовый уровень (не библиотека)
🏆 CloudCastle33,8быстрейшее среди библиотек
beste157,9аналог
ergebnis162,4аналог
lcobucci163,4аналог
symfony223,2аналог
carbon911,9аналог

5. Потребление памяти библиотекой

Прирост памяти самой библиотеки на 200 000 вызовов now() (изолированный процесс, без веса автолоадера).

РешениеПамять (KB)Итог
new¹1базовый уровень (не библиотека)
🏆 beste3легчайшее среди библиотек
ergebnis5аналог
lcobucci6аналог
symfony30аналог
CloudCastle56аналог
carbon3 436аналог

6. Утечки памяти

Рост памяти после прогрева за 200 000 вызовов now() (0 — утечек нет).

РешениеПамять (KB)Итог
🏆 CloudCastle0без утечек
symfony0без утечек
carbon0без утечек
lcobucci0без утечек
beste0без утечек
ergebnis0без утечек
new¹0базовый уровень (не библиотека)

7. Пик памяти процесса

Пик памяти изолированного процесса на 200 000 вызовов now().

РешениеПамять (KB)Итог
🏆 CloudCastle6 950легчайшее среди библиотек
symfony6 950аналог
lcobucci6 950аналог
beste6 950аналог
ergebnis6 950аналог
new¹6 950базовый уровень (не библиотека)
carbon10 226аналог

8. Качество кода

Инструмент🏆 CloudCastlesymfonycarbonlcobuccibesteergebnis
PHPStan✅ max + strict✅ + strict✅ + strict✅ + strict
Psalm✅ level 1✅ (monorepo)
PHPMD
PHPCS / CS-Fixer✅ PSR-12 + fixer✅ fixer✅ fixer
Rector
Deptrac (слои архитектуры)
Мутационное тестирование (Infection)✅ MSI —
Покрытие строк (живое)✅ —
Всего🏆 823324

Инструменты аналогов — по require-dev их опубликованных дистрибутивов (снапшот июль 2026); symfony/clock — по монорепозиторию symfony/symfony. Метрики CloudCastle — живые результаты локального прогона.

¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.

Честная выжимка

Плюсы:

  • функциональный суперсет всех сравниваемых PSR-20 библиотек вместе взятых, включая календарную работу уровня Carbon (CalendarDate);
  • детерминизм времени в тестах без глобального состояния (изолированные экземпляры часов) и со скоуп-подменой там, где глобальность удобна;
  • наносекундная арифметика длительностей с контролем переполнения — тихих искажений не бывает;
  • лёгкие зависимости: только psr/clock и cloud-castle/inflector (корректные склонения без ICU/ext-intl) — на порядок легче связки Carbon + symfony/translation.

Минусы:

  • моложе и менее распространён, чем symfony/clock и nesbot/carbon: меньше ответов на StackOverflow;
  • нет готовой интеграции с Laravel-экосистемой (фасады, Eloquent-касты дат), как у Carbon, — сознательное ограничение области: пакет фреймворк-агностичен (сам календарный API CalendarDate — от арифметики и предикатов до парсинга относительных строк и diffForHumans — Carbon-паритетен).

Рекомендации по применению:

  • Бизнес-сервисы и финтех — внедряйте ClockInterface, в тестах MockClock/FrozenClock: детерминированные проверки TTL, дедлайнов, retry.
  • Очереди, лимитеры, кэшиMonotonicClock для интервалов, устойчивых к переводу системных часов; Deadline для тайм-аутов.
  • Профилирование и метрикиStopwatch с кругами; timestamp() на горячих путях вместо now()->getTimestamp().
  • Симуляции и сценарные тестыStepClock/QueueClock/ScaledClock.
  • Календарь и локализацияCalendarDate для арифметики месяцев/лет без переполнения (addMonthsNoOverflow()), детерминированного парсинга относительных строк (parse('next friday') от часов приложения), форматтеров (toDateString(), ISO/RFC/ATOM), предикатов (isWeekend(), isToday()), разниц (diffInDays()) и diffForHumans() на 6 языках без ICU/ext-intl.
  • Не стоит брать только ради тесной интеграции с Laravel (фасады, Eloquent-касты дат) — это единственное, чем Carbon здесь богаче.

Разработка

composer install
composer check    # линтеры + статический анализ + тесты
composer fix      # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci       # полный CI-пайплайн локально

Полный список команд с описаниями: composer run-script --list.

Документация

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano