gamez / duration
Working with durations made easy
Fund package maintenance!
Requires
- php: ^8.3
- ext-ctype: *
Requires (Dev)
- phpstan/phpstan: ^2.2.9
- phpunit/phpunit: ^12.5.33
README
Working with durations made easy.
Do you like to use DateInterval to compute and work with durations? Me neither, so let's fix that!
Installation
You can install the package with Composer:
composer require gamez/duration
You can then use Duration:
<?php use Gamez\Duration; $duration = Duration::make('13 minutes 37 seconds'); // or start with nothing $duration = Duration::none();
Reference
Supported input values
DateIntervals
use Gamez\Duration; Duration::make('PT13M37S'); Duration::make(new DateInterval('PT13M37S'));
Colon notation
use Gamez\Duration; Duration::make('13:37'); // minutes:seconds Duration::make('13:37:37'); // hours:minutes:seconds
Textual notation
A textual notation is any value that can be processed by DateInterval::createFromDateString()
use Gamez\Duration; Duration::make('13 minutes 37 seconds');
Weeks, months, and years
Weeks are normalized to seven days, so P1W is represented as P7D.
Months and years do not have a fixed length. When Duration compares, adds, subtracts, multiplies, divides, or
normalizes such values, it evaluates them relative to a cached UTC date and time. This avoids daylight-saving
transitions, but results can still depend on the calendar date. For example, one month can span 28 to 31 days and one
year can span 365 or 366 days.
If exact elapsed time matters, prefer days, hours, minutes, and seconds. Use months and years only when calendar-relative behavior is intended.
Transformations
When transformed, a Duration will be
- converted to a DateInterval representation
- optimized in the sense that an input value of 60 seconds would result in an output value of "1 minute", for example "PT60S" would be converted to "PT1H"
use Gamez\Duration; $duration = Duration::make('8 days 29 hours 77 minutes'); echo (string) $duration; // P9DT6H17M echo json_encode($duration); // "P9DT6H17M"
Comparisons
use Gamez\Duration; $oneSecond = Duration::make('1 second'); $sixtySeconds = Duration::make('60 seconds'); $oneMinute = Duration::make('1 minute'); $oneHour = Duration::make('1 hour'); $oneSecond->isSmallerThan($oneMinute); // true $oneHour->isLargerThan($oneMinute); // true $oneMinute->equals($sixtySeconds); // true $durations = [$oneMinute, $oneSecond, $oneHour, $sixtySeconds]; usort($durations, function ($a, $b) { return $a->compareTo($b); }); // -> [$oneSecond, $sixtySeconds, $oneMinute, $oneHour]
Operations
Results will always be rounded by the second.
use Gamez\Duration; $thirty = Duration::make('30 seconds'); echo $thirty->withAdded('31 seconds'); // PT1M1S echo $thirty->withSubtracted('29 seconds'); // PT1S echo $thirty->multipliedBy(3); // PT1M30S echo $thirty->dividedBy(2.5); // PT12S $thirty->multipliedBy(-1); // InvalidArgumentException $thirty->withSubtracted('31 seconds'); // InvalidArgumentException
Roadmap
- Support more input formats
- Add "output for humans" (like colon notation)
- Support precision (similar to spatie/period)
- ...