PHPackages                             bermudaphp/duration - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. bermudaphp/duration

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

bermudaphp/duration
===================

An immutable PHP library for handling time durations with ISO 8601 support

v1.0(1y ago)01MITPHPPHP ^8.4

Since May 9Pushed 1y ago1 watchersCompare

[ Source](https://github.com/bermudaphp/duration)[ Packagist](https://packagist.org/packages/bermudaphp/duration)[ RSS](/packages/bermudaphp-duration/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (0)

Duration
========

[](#duration)

[![PHP Version](https://camo.githubusercontent.com/9c2f8ad80d34105266a94c4c06234f8ed18c968d3595039c2d9a7becd1e71c8b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e342d626c75652e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](https://opensource.org/licenses/MIT)

*Read this in other languages: [Русский](README.ru.md)*

Overview
--------

[](#overview)

`Duration` is an immutable wrapper class for working with time durations with ISO 8601 support. It provides a comprehensive API for creating, manipulating, formatting, and comparing time durations in a type-safe and consistent manner.

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Installation](#installation)
- [Basic Usage](#basic-usage)
- [Factory Methods](#factory-methods)
- [ISO 8601 Support](#iso-8601-support)
- [Conversion Methods](#conversion-methods)
- [Arithmetic Operations](#arithmetic-operations)
- [Comparison Operations](#comparison-operations)
- [Increment and Decrement Operations](#increment-and-decrement-operations)
- [Formatting Methods](#formatting-methods)
- [Serialization](#serialization)
- [DateInterval Conversion](#dateinterval-conversion)
- [Examples](#examples)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)

Features
--------

[](#features)

- **Immutable Design**: All operations return new instances, preserving the original
- **Fluent Interface**: Method chaining for cleaner code
- **ISO 8601 Support**: Parse and generate ISO 8601 duration strings (e.g., `P1Y2M3DT4H5M6S`)
- **Comprehensive Time Units**: Convert between seconds, minutes, hours, days, weeks, months, and years
- **Advanced Comparison**: Compare durations with support for ALL/ANY modes when working with arrays
- **Increment/Decrement**: Convenient methods for increasing or decreasing durations
- **Multiple Formatting Options**: Human-readable, custom format templates, and component arrays
- **Serialization Support**: JSON serialization built-in
- **DateInterval Integration**: Convert to and from PHP's DateInterval class

Installation
------------

[](#installation)

```
composer require bermudaphp/duration
```

Basic Usage
-----------

[](#basic-usage)

```
use Bermuda\Stdlib\Duration;

// Create a duration of 1 hour and 30 minutes
$duration = new Duration(5400);

// Get total seconds
echo $duration->toSeconds(); // 5400

// Convert to minutes
echo $duration->toMinutes(); // 90

// Convert to hours
echo $duration->toHours(); // 1

// Get the ISO 8601 representation
echo $duration->toISO8601(); // "PT1H30M"

// Get a human-readable representation
echo $duration->toHumanReadable(); // "01:30:00"
```

Factory Methods
---------------

[](#factory-methods)

`Duration` provides multiple factory methods for creating instances:

```
// From specific time units
$fromSeconds = Duration::fromSeconds(60);       // 60 seconds
$fromMinutes = Duration::fromMinutes(5);        // 5 minutes
$fromHours = Duration::fromHours(2);            // 2 hours
$fromDays = Duration::fromDays(1);              // 1 day
$fromWeeks = Duration::fromWeeks(2);            // 2 weeks
$fromMonths = Duration::fromMonths(3);          // 3 months
$fromYears = Duration::fromYears(1);            // 1 year

// From ISO 8601 string
$fromISO = Duration::fromISO8601('P1Y2M3DT4H5M6S');

// From DateInterval
$interval = new \DateInterval('P1DT6H');
$fromInterval = Duration::fromDateInterval($interval);
```

ISO 8601 Support
----------------

[](#iso-8601-support)

`Duration` fully supports the ISO 8601 duration format:

```
// Validate ISO 8601 strings
$isValid = Duration::validate('P1Y2M3DT4H5M6S'); // true
$isInvalid = Duration::validate('P1X'); // false

// Create from ISO 8601 string
$duration = Duration::fromISO8601('P1Y2M3DT4H5M6S');

// Convert to ISO 8601 string
echo $duration->toISO8601(); // "P1Y2M3DT4H5M6S"
```

### ISO 8601 Format Rules

[](#iso-8601-format-rules)

- Format: `P[n]Y[n]M[n]DT[n]H[n]M[n]S`
- `P` is the duration designator (for period) placed at the start
- `Y` is the year designator
- `M` is the month designator
- `D` is the day designator
- `T` is the time designator (required if any time components are used)
- `H` is the hour designator
- `M` is the minute designator
- `S` is the second designator

Example: `P3Y6M4DT12H30M5S` represents a duration of 3 years, 6 months, 4 days, 12 hours, 30 minutes, and 5 seconds.

Conversion Methods
------------------

[](#conversion-methods)

Convert a duration to different time units:

```
$duration = Duration::fromISO8601('P1Y2M3DT4H5M6S');

echo $duration->toSeconds(); // Total seconds
echo $duration->toMinutes(); // Total minutes (rounded down)
echo $duration->toHours();   // Total hours (rounded down)
echo $duration->toDays();    // Total days (rounded down)
echo $duration->toWeeks();   // Total weeks (rounded down)
echo $duration->toMonths();  // Total months (rounded down)
echo $duration->toYears();   // Total years (rounded down)
```

Arithmetic Operations
---------------------

[](#arithmetic-operations)

Perform arithmetic operations on durations:

```
$duration1 = new Duration(3600); // 1 hour
$duration2 = new Duration(1800); // 30 minutes

// Addition
$sum = $duration1->add($duration2); // 1 hour 30 minutes

// Adding specific time units
$plusOneHour = $duration1->addHours(1);     // Add 1 hour
$plusTenMinutes = $duration1->addMinutes(10); // Add 10 minutes
$plusYear = $duration1->addYears(1);        // Add 1 year

// Subtraction (throws exception if result would be negative)
$difference = $duration1->strictSubtract($duration2); // 30 minutes

// Safe subtraction (returns zero if result would be negative)
$safeDifference = $duration1->subtract($duration2); // 30 minutes

// Subtracting specific time units (throws exception if result would be negative)
$minusOneHour = $duration2->subtractHours(1); // Exception!
$minusTenMinutes = $duration2->subtractMinutes(10); // 20 minutes

// Multiplication
$doubled = $duration1->multiply(2); // 2 hours

// Division
$halved = $duration1->divide(2); // 30 minutes
```

Comparison Operations
---------------------

[](#comparison-operations)

Compare durations with various methods:

```
$duration1 = new Duration(3600); // 1 hour
$duration2 = new Duration(7200); // 2 hours
$duration3 = new Duration(3600); // 1 hour

// Compare two durations
$comparisonResult = $duration1->compareTo($duration2); // -1 (less than)

// Equality
$isEqual = $duration1->equals($duration3); // true
$isNotEqual = $duration1->equals($duration2); // false

// Greater/less than
$isLess = $duration1->lessThan($duration2); // true
$isLessOrEqual = $duration1->lessThanOrEqual($duration3); // true
$isGreater = $duration2->greaterThan($duration1); // true
$isGreaterOrEqual = $duration1->greaterThanOrEqual($duration3); // true

// Check if between two durations
$isBetween = $duration1->between(
    new Duration(1800),  // 30 minutes
    new Duration(10800), // 3 hours
    true                // inclusive (default)
); // true
```

### Comparing with Arrays of Durations

[](#comparing-with-arrays-of-durations)

Compare a duration against multiple durations using ALL or ANY modes:

```
$duration = new Duration(3600); // 1 hour
$durations = [
    new Duration(1800),  // 30 minutes
    new Duration(7200),  // 2 hours
    new Duration(10800)  // 3 hours
];

// ALL mode (default) - the condition must be true for ALL durations in the array
$isLessThanAll = $duration->lessThan($durations, Duration::COMPARE_ALL); // false
$isGreaterThanAll = $duration->greaterThan($durations, Duration::COMPARE_ALL); // false

// ANY mode - the condition must be true for AT LEAST ONE duration in the array
$isLessThanAny = $duration->lessThan($durations, Duration::COMPARE_ANY); // false
$isGreaterThanAny = $duration->greaterThan($durations, Duration::COMPARE_ANY); // true
```

Increment and Decrement Operations
----------------------------------

[](#increment-and-decrement-operations)

Increment or decrement durations:

```
$duration = Duration::fromMinutes(5); // 5 minutes

// Increment by 1 second
$incremented = $duration->increment(); // 5 minutes 1 second

// Increment by specific amount
$incrementedByMinute = $duration->incrementBy(60); // 6 minutes

// Increment by another duration
$anotherDuration = Duration::fromMinutes(10);
$combined = $duration->incrementByDuration($anotherDuration); // 15 minutes

// Decrement (throws exception if result would be negative)
$decremented = $duration->decrement(); // 4 minutes 59 seconds

// Decrement by specific amount (throws exception if result would be negative)
$decrementedByMinute = $duration->decrementBy(60); // 4 minutes

// Safe decrement (returns zero if result would be negative)
$safeDecremented = $duration->safeDecrement(); // 4 minutes 59 seconds

// Safe decrement by specific amount (returns zero if result would be negative)
$safeDecrementedByTooMuch = $duration->safeDecrementBy(600); // 0 seconds
```

Formatting Methods
------------------

[](#formatting-methods)

Format durations in different ways:

```
$duration = Duration::fromISO8601('P1Y2M3DT4H5M6S');

// Convert to array of components
$array = $duration->toArray();
/*
[
    'years' => 1,
    'months' => 2,
    'days' => 3,
    'hours' => 4,
    'minutes' => 5,
    'seconds' => 6
]
*/

// Format using a custom template
$formatted = $duration->format('Years: %Y, Months: %M, Days: %D, Time: %H:%I:%S');
// "Years: 01, Months: 02, Days: 03, Time: 04:05:06"

// Human-readable format
$readable = $duration->toHumanReadable(); // "01:02:03:04:05:06"
```

### Format Placeholders

[](#format-placeholders)

The `format()` method supports the following placeholders:

PlaceholderDescription`%Y`Years (zero-padded)`%M`Months (zero-padded)`%D`Days (zero-padded)`%H`Hours (zero-padded)`%I`Minutes (zero-padded)`%S`Seconds (zero-padded)`%T`Total secondsSerialization
-------------

[](#serialization)

The `Duration` class implements `JsonSerializable` and `Stringable` interfaces:

```
$duration = Duration::fromISO8601('P1Y2M3DT4H5M6S');

// Convert to string (ISO 8601 format)
echo (string)$duration; // "P1Y2M3DT4H5M6S"

// JSON serialization
$json = json_encode($duration);
/*
{
    "seconds": 37090998,
    "iso8601": "P1Y2M3DT4H5M6S",
    "components": {
        "years": 1,
        "months": 2,
        "days": 3,
        "hours": 4,
        "minutes": 5,
        "seconds": 6
    }
}
*/
```

DateInterval Conversion
-----------------------

[](#dateinterval-conversion)

Convert between `Duration` and PHP's `DateInterval`:

```
// Create from DateInterval
$interval = new \DateInterval('P1YT6H');
$duration = Duration::fromDateInterval($interval);

// Convert to DateInterval
$newInterval = $duration->toDateInterval();
echo $newInterval->format('%y years, %h hours'); // "1 years, 6 hours"
```

Examples
--------

[](#examples)

### Creating a Countdown Timer

[](#creating-a-countdown-timer)

```
// Create a 5-minute countdown timer
$countdownDuration = Duration::fromMinutes(5);

// Simulate countdown (in a real application, this would be in a loop with sleep)
for ($i = 0; $i < 5; $i++) {
    echo "Remaining: " . $countdownDuration->toHumanReadable() . PHP_EOL;
    $countdownDuration = $countdownDuration->decrementBy(60); // Decrease by 1 minute
}

echo "Time's up!";
```

### Working with Events

[](#working-with-events)

```
// Event duration
$eventDuration = Duration::fromHours(2);

// Check if event is longer than 1 hour but shorter than 3 hours
$isReasonableLength = $eventDuration->between(
    Duration::fromHours(1),
    Duration::fromHours(3)
);

// Create a 15-minute break
$breakDuration = Duration::fromMinutes(15);

// Add 15-minute break at the end
$totalDuration = $eventDuration->add($breakDuration);

echo "Total event duration: " . $totalDuration->toHumanReadable();
```

### Tracking Task Time

[](#tracking-task-time)

```
// Start time stored in database as seconds
$taskTimeSeconds = 3600; // 1 hour already tracked
$taskDuration = new Duration($taskTimeSeconds);

// User works for 45 more minutes
$additionalTime = Duration::fromMinutes(45);
$updatedTaskDuration = $taskDuration->add($additionalTime);

// Get task time components for display
$components = $updatedTaskDuration->toArray();
$hours = $components['hours'] ?? 0;
$minutes = $components['minutes'] ?? 0;

echo "Task time: {$hours}h {$minutes}m";
```

Testing
-------

[](#testing)

Run the PHPUnit tests:

```
composer test
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

This project is licensed under the MIT License - see the LICENSE file for details.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance49

Moderate activity, may be stable

Popularity1

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

374d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20490712?v=4)[Andrey Shelamkoff](/maintainers/Shelamkoff)[@Shelamkoff](https://github.com/Shelamkoff)

---

Top Contributors

[![Shelamkoff](https://avatars.githubusercontent.com/u/20490712?v=4)](https://github.com/Shelamkoff "Shelamkoff (17 commits)")

---

Tags

durationduration-parserimmutableiso8601iso8601-durationphpphp84value-objectphpValue Objectimmutabledurationiso8601php84iso8601-durationduration-parser

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bermudaphp-duration/health.svg)

```
[![Health](https://phpackages.com/badges/bermudaphp-duration/health.svg)](https://phpackages.com/packages/bermudaphp-duration)
```

###  Alternatives

[sybio/gif-frame-extractor

PHP class that separates all the frames (and their duration) of an animated GIF

179417.2k8](/packages/sybio-gif-frame-extractor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
