Skip to content

Feature Truncating clock

github-actions[bot] edited this page Jul 14, 2026 · 1 revision

✂️ Усечение моментов — TruncatingClock

← Возможности · Главная · Сравнение

Декоратор, округляющий моменты вниз до границы единицы: секунда, минута, час, сутки. Обобщение идеи MinuteClock из beste/clock на произвольные единицы.

Принцип работы

use CloudCastle\Clock\TruncatingClock;
use CloudCastle\Clock\TruncationUnit;
use CloudCastle\Clock\SystemClock;

$bySecond = new TruncatingClock(SystemClock::utc());                        // до секунды
$byMinute = TruncatingClock::toMinute(SystemClock::utc());                  // паритет с beste
$byHour = new TruncatingClock(SystemClock::utc(), TruncationUnit::Hour);
$byDay = new TruncatingClock(SystemClock::utc(), TruncationUnit::Day);

$byMinute->now()->format('H:i:s.u'); // 12:34:00.000000

Единицы задаёт enum TruncationUnit: Second, Minute, Hour, Day.

При withTimezone() момент сначала переводится в целевую зону и только затем усекается — границы часов и суток зонозависимы, и «начало дня» в Москве отличается от начала дня в UTC:

$frozen = FrozenClock::from('2026-05-20 23:30:00', 'UTC');
$clock = (new TruncatingClock($frozen, TruncationUnit::Day))->withTimezone('Europe/Moscow');

$clock->now()->format('Y-m-d H:i'); // 2026-05-21 00:00 — по Москве уже наступил новый день

Плюсы

  • Стабильные ключи кэша: все запросы одной минуты получают один момент.
  • Группировка метрик по временным окнам без ручной арифметики.
  • Зонозависимое усечение до суток — корректные «сегодня» для любой аудитории.

Минусы

  • microtime() всегда с нулевой дробной частью — не для замеров длительностей.

✅ Рекомендуется

  • Ключи кэшей и rate-limit-бакетов: truncated->timestamp().
  • Отсечки «начало дня» в отчётах с учётом зоны пользователя.

❌ Антипаттерны

  • Усечение до суток в UTC для локальных бизнес-дат — «сегодня» уедет на день.

Схема фичи

flowchart LR
    IN[Внутренние часы] --> TC["TruncatingClock(unit)"]
    TC -->|Second| S["12:34:56.000000"]
    TC -->|Minute| M["12:34:00"]
    TC -->|Hour| H["12:00:00"]
    TC -->|Day| D["00:00:00"]
Loading

Жизненный цикл с учётом зоны

flowchart TD
    A["now()"] --> B["inner.now()"]
    B --> C{"есть withTimezone()?"}
    C -->|да| D["перевести момент в целевую зону"]
    C -->|нет| E["unit.truncate(момент)"]
    D --> E
    E --> F["момент на границе единицы"]
Loading

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

Возможность Clock symfony/clock lcobucci/clock beste/clock nesbot/carbon ergebnis/clock 🏆 Победитель
Усечение до минуты Clock + beste/clock
Секунда/час/сутки Clock
Зонозависимое усечение Clock

Clone this wiki locally