Take the State of PHP 2026 Survey →

Duration class View as Markdown

Implemented (PHP 8.6)
Authors
Tim Düsterhus, tim@tideways-gmbh.com, Derick Rethans, derick@php.net
Date
2026-06-18
Version
1.0
Implementation
https://github.com/php/php-src/commit/1cf46237a56540c14d84d0f04b245a10d4ee5bc5 and https://github.com/php/php-src/commit/ed2ffe6f70f6d7f8391f46b1fac88b60b97cdb6b
Source
wiki.php.net/rfc/duration_class

Votes

Implement the Time\Duration class as outlined in the RFC? closed
Yes
35
No
1
Abstain
2
38 voters
alcaeus Yes 2026-07-23 08:43
alec No 2026-07-17 17:28
alexandredaubois Yes 2026-07-21 13:00
asgrim Yes 2026-07-17 17:17
ashnazg Yes 2026-07-22 15:20
beberlei Yes 2026-07-17 19:37
brzuchal Yes 2026-07-29 05:47
bwoebi Abstain 2026-07-25 14:18
cpriest Yes 2026-07-20 15:11
crell Yes 2026-07-20 02:18
daniels Yes 2026-07-30 21:03
derick Yes 2026-07-17 18:00
duncan3dc Yes 2026-07-17 17:06
edorian Yes 2026-07-20 10:56
enorris Yes 2026-07-28 19:12
ericmann Yes 2026-07-27 17:03
galvao Yes 2026-07-19 05:20
girgias Yes 2026-07-19 14:14
iliaa Yes 2026-07-19 14:19
ilutov Yes 2026-07-17 16:50
jimw Yes 2026-07-20 17:31
jordikroon Yes 2026-07-17 16:44
kalle Yes 2026-07-17 16:38
kocsismate Yes 2026-07-17 20:56
marandall Yes 2026-07-24 11:22
mbeccati Yes 2026-07-20 08:31
pajoye Yes 2026-07-19 13:16
ramsey Yes 2026-07-25 01:02
sebastian Yes 2026-07-20 13:18
sergey Yes 2026-07-22 08:09
shivam Yes 2026-07-20 12:07
svpernova09 Yes 2026-07-28 14:32
theodorejb Yes 2026-07-17 17:59
timwolla Yes 2026-07-17 16:35
trowski Yes 2026-07-30 16:42
weierophinney Yes 2026-07-20 17:26
weilindu Yes 2026-07-24 18:04
zeriyoshi Abstain 2026-07-22 08:19
Should the mathematical operation methods of Time\Duration use full or abbreviated names? closed
multiplyBy, divideBy, negate, absolute
30
mul, divBy, neg, abs
2
Abstain
3
35 voters
alcaeus multiplyBy, divideBy, negate, absolute 2026-07-23 08:43
alexandredaubois multiplyBy, divideBy, negate, absolute 2026-07-21 13:00
asgrim multiplyBy, divideBy, negate, absolute 2026-07-17 17:17
ashnazg multiplyBy, divideBy, negate, absolute 2026-07-22 15:21
beberlei multiplyBy, divideBy, negate, absolute 2026-07-17 19:37
brzuchal multiplyBy, divideBy, negate, absolute 2026-07-29 05:47
bwoebi mul, divBy, neg, abs 2026-07-25 14:18
crell Abstain 2026-07-20 02:18
daniels multiplyBy, divideBy, negate, absolute 2026-07-30 21:03
derick multiplyBy, divideBy, negate, absolute 2026-07-17 18:00
duncan3dc multiplyBy, divideBy, negate, absolute 2026-07-17 17:07
edorian multiplyBy, divideBy, negate, absolute 2026-07-20 10:55
enorris multiplyBy, divideBy, negate, absolute 2026-07-28 19:12
ericmann multiplyBy, divideBy, negate, absolute 2026-07-27 17:03
galvao multiplyBy, divideBy, negate, absolute 2026-07-19 05:20
girgias multiplyBy, divideBy, negate, absolute 2026-07-19 14:14
iliaa mul, divBy, neg, abs 2026-07-19 14:19
ilutov multiplyBy, divideBy, negate, absolute 2026-07-17 16:50
jordikroon multiplyBy, divideBy, negate, absolute 2026-07-17 16:44
kalle multiplyBy, divideBy, negate, absolute 2026-07-17 16:38
kocsismate multiplyBy, divideBy, negate, absolute 2026-07-17 20:56
marandall multiplyBy, divideBy, negate, absolute 2026-07-24 11:22
mbeccati multiplyBy, divideBy, negate, absolute 2026-07-20 08:31
pajoye multiplyBy, divideBy, negate, absolute 2026-07-18 05:51
ramsey multiplyBy, divideBy, negate, absolute 2026-07-25 01:02
sebastian multiplyBy, divideBy, negate, absolute 2026-07-20 13:18
sergey multiplyBy, divideBy, negate, absolute 2026-07-22 08:09
shivam multiplyBy, divideBy, negate, absolute 2026-07-20 12:08
svpernova09 multiplyBy, divideBy, negate, absolute 2026-07-28 14:32
theodorejb multiplyBy, divideBy, negate, absolute 2026-07-17 17:59
timwolla Abstain 2026-07-17 16:35
trowski multiplyBy, divideBy, negate, absolute 2026-07-30 16:42
weierophinney multiplyBy, divideBy, negate, absolute 2026-07-20 17:26
weilindu multiplyBy, divideBy, negate, absolute 2026-07-24 18:04
zeriyoshi Abstain 2026-07-22 08:19

Discussions on the mailing list

[RFC] Duration class
· 103 messages
[VOTE] Duration class
· 2 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:50 UTC

Introduction

Measuring and defining elapsed time is a ubiquitous concept in programming languages. Use cases where accurately defining such duration include defining timeouts for network requests, defining (exponential) back-off policies or defining operations that need to happen on a fixed schedule. PHP does not yet have a way to represent “stop-watch time” duration in a structured and intuitive way.

Instead existing APIs resort to int parameters representing a number of seconds, milliseconds, nanoseconds or any other unit that appears to be appropriate for a given use case. Sometimes durations are also split into separate parameters defining the $seconds and $microsecond separately. And sometimes it's a floating point value which comes with its own issues due to a possible lack of precision.

The existing DateInterval class is also unsuitable to define durations for the use-cases previously mentioned, due to its support for days and larger units which cannot be unambiguously mapped into a fixed number of seconds due to daylight saving time and months having different lengths.

This RFC proposes the addition a Time\Duration class that represents durations as measured by a “stop-watch” or an “egg-timer” in a structured way with nanosecond precision.

<?php
 
// Sleep for half a second
sleep(\Time\Duration::fromMilliseconds(500));
 
?>

Proposal

Add a new always-available class Time\Duration with the following stub:

<?php
 
namespace Time;
 
/**
 * Represents a “stop-watch” or “egg-timer” duration as an abstraction over a number
 * of (fractional) seconds with nanosecond precision. It is unaffected by any timezones
 * or “time and date” as shown on a clock.
 *
 * The maximum representable range is 9223372035999999999 nanoseconds (roughly 292 years).
 * Any operation that will overflow, will throw a Time\TimeException.
 *
 * @strict-properties
 */
final readonly class Duration
{
    /**
     * Will be limited to 9_223_372_035 even on 64-bit platforms to allow for a possible
     * future scope `->getTotalNanoseconds(): int`
     */
    public readonly int $seconds;
    public readonly int $nanoseconds;
 
    /**
     * Will be normalized to false if both $seconds and $nanoseconds are 0.
     */
    public readonly bool $negative;
 
    /**
     * Create a duration representing $seconds seconds and $nanoseconds nanoseconds. Neither parameter
     * may be negative. $nanoseconds must be less than 1_000_000_000 (the number of nanoseconds in a
     * second).
     *
     * This constructor creates a Duration from its “atomic” components.
     */
    public static function fromSeconds(int $seconds, int $nanoseconds = 0): self
    {
    }
 
    /**
     * Create a duration representing $nanoseconds nano-seconds. $nanoseconds must not be negative.
     */
    public static function fromNanoseconds(int $nanoseconds): self
    {
    }
 
    /**
     * Create a duration representing $microseconds micro-seconds. $microseconds must not be negative.
     */
    public static function fromMicroseconds(int $microseconds): self
    {
    }
 
    /**
     * Create a duration representing $milliseconds milli-seconds. $milliseconds must not be negative.
     */
    public static function fromMilliseconds(int $milliseconds): self
    {
    }
 
    /**
     * Create a duration representing $minutes minutes. $minutes must not be negative.
     */
    public static function fromMinutes(int $minutes): self
    {
    }
 
    /**
     * Create a duration representing $hours hours. $hours must not be negative.
     */
    public static function fromHours(int $hours): self
    {
    }
 
    /**
     * Parse a ISO-8601 duration string. ISO-8601 duration strings with a date component will be rejected.
     * The biggest allowed component is H.
     */
    public static function fromIso8601DurationString(string $specification): self
    {
    }
 
    /**
     * Negates the duration.
     *
     * @return self -$this
     */
    public function negate(): self
    {
    }
 
    /**
     * Returns the duration with `$seconds` and `$nanoseconds` unchanged and
     * `$negative` set to `false`.
     *
     * @return self abs($this)
     */
    public function absolute(): self
    {
    }
 
    /**
     * Add the given duration to the duration.
     *
     * @return self $this + $duration
     */
    public function add(self $duration): self
    {
    }
 
    /**
     * Subtract the given duration from the duration.
     *
     * @return self $this - $duration
     */
    public function sub(self $duration): self
    {
    }
 
    /**
     * Multiply the length of the duration by the given factor. $factor must not be negative.
     * 
     * @return self $this * $factor
     */
    public function multiplyBy(int $factor): self
    {
    }
 
    /**
     * Divide the length of the duration by the given divisor. $divisor must be positive.
     *
     * Fractional nanoseconds will be truncated.
     *
     * @return self $this / $factor
     */
    public function divideBy(int $divisor): self
    {
    }
 
    /**
     * Returns -1, 0, 1 if $a is less than, equal to, or greater than $b respectively.
     */
    public static function compare(self $a, self $b): int
    {
    }
}

The Time\Duration class will also implement internal “comparison handlers”, which means that direct comparisons with operators such as < will work. Other operators (such as + for addition) will not be overloaded.

Additionally add the Time\TimeException base exception as per the Throwable policy:

namespace Time;
 
class TimeException extends \Exception { }

Naming of the mathematical operations

According to PHP’s naming policy “Abbreviations and acronyms as well as initialisms SHOULD be avoided wherever possible”, which is why the RFC proposes full verbs for multiplication, division, negation and taking absolutes.

At the same time the naming policy also specifies that “Diverging from this policy […] is allowed to keep internal consistency within a single extension, if the name follows an established, language-agnostic standard, or for other reasons, if those reasons are properly justified and voted on as part of the RFC process”.

While there naturally is no existing precedent within the extension (or namespace), there is cross-extension precedent for abbreviated names in ext/bcmath, ext/gmp, the standard library, and PHP’s own tokenizer, specifically:

  • BcMath\Number::mul() BcMath\Number::div(), bcmul(), bcdiv()
  • gmp_mul(), gmp_div(), gmp_neg(), gmp_abs()
  • abs(), intdiv(), fdiv()
  • T_MUL_EQUAL, T_DIV_EQUAL

There is also some cross-language precedent. JavaScript’s Temporal.Duration has abs(). Rust’s std::time::Duration has checked_mul() and checked_div().

The RFC therefore leaves up the choice between full and abbreviated names up to a (weighted) secondary vote. For multiplication the By suffix is dropped when abbreviating. Division will keep the By suffix (divBy) to enable a future scope divInto method that divides a Duration by a Duration.

The new polling API

If this RFC is accepted for PHP 8.6, the polling API introduced in PHP RFC: Polling API for PHP 8.6 will be adjusted to make use of the Time\Duration class instead of separate $timeout and $timeoutMicroseconds parameters:

namespace Io\Poll;
 
final class Context
{
    /**
     * […]
     * 
     * @param ?Time\Duration $timeout Timeout.
     *        null means wait indefinitely.
     *        Time\Duration::fromNanoseconds(0) means return immediately (non-blocking poll).
     *        Must be !$timeout->negative
     * 
     * […]
     */
    public function wait(
        ?Time\Duration $timeout = null,
        ?int $maxEvents = null
    ): array {}
}

Passing Duration objects to APIs unable to handle nanosecond precision

This RFC leaves the behavior of passing a Time\Duration object that has more precision than an API can handle to the target API in question, since depending on the use case a different behavior might be the correct.

A non-exhaustive list of possible options:

  • Always round *up* to the nearest representable value. This behavior makes most sense for “at least this amount of time” APIs (e.g. sleep()).
  • Always round *down* to the nearest representable value.
  • Throw for unrepresentable values. This behavior makes sense if the rounding error would be unacceptably large.

Design Considerations

Time\Duration is intended as the first part and basic building block of a modernized date and time library for PHP, while already providing value by itself. For this initial version the exposed API is intentionally small, while including all important parts for future classes to build onto.

Its design is roughly modeled after Golang’s time.Duration, Java’s java.time.Duration, and Rust’s std::time::Duration, which just like Time\Duration are a structured representation of a number of nanoseconds.

The split between $seconds and $nanoseconds in the public API is intended to match how seconds are used as a base unit in human communication and science. It also improves compatibility with 32-bit versions of PHP, since signed 32-bit integers are sufficiently large to represent the number of nanoseconds in a second, while the separate seconds component allows to represent roughly 68 years. $seconds will be limited to 9_223_372_035 on 64-bit systems (roughly 292 years) to possibly allow representing the entire duration as a single nanosecond value in future scope.

Creating Duration objects happens via named constructors for all possible resolutions such that users are able to select the most appropriate resolution for their use case. Except for the fromSeconds() “base” constructor (which matches the second and nanosecond split described above) all constructors intentionally only take a single value in order to avoid multiple input combinations for the same constructor misleadingly resulting in the same duration due to overflow (e.g. 1 millisecond and 1500 microseconds being equivalent to 2 milliseconds and 500 microseconds). For the fromSeconds() constructor an overflow in the nanosecond component is rejected.

Negative durations are represented by an explicit $negative property. This makes it easy to deal with absolute values by just ignoring the value of $negative. It also avoids ambiguity with regard to signs for negative durations: Should both $seconds and $nanoseconds be negative for a negative duration?

Creating a negative duration intentionally requires a separate call to ->negate(), since use cases for those are expected to be rare. They are expected to mainly come up when subtracting one duration from another and when calculating differences between two “Instants” after more parts of the modernized date and time library are added.

Examples

Note that these examples show possible hypothetical use-cases. The RFC does not propose a change to existing functions to accept Time\Duration objects, except for the Io\Poll\Context as described previously.

<?php
 
use Time\Duration;
 
$oneSecond = Duration::fromSeconds(1);
$halfSecond = $oneSecond->divideBy(2);
 
$onePointFiveSeconds = $oneSecond->add($halfSecond);
 
// Sleep for 1.5 seconds
sleep($onePointFiveSeconds);
 
$negativeHour = Duration::fromHours(1)->negate();
 
$durations = [
    $oneSecond,
    $negativeHour,
    $onePointFiveSeconds,
    $halfSecond,
];
 
usort($durations, Duration::compare(...)); // Will sort to [-1h, 0.5s, 1s, 1.5s]
 
$baseDelay = Duration::fromMilliseconds(100);
$attempt = 5;
$delay = $baseDelay->multiplyBy(2 ** $attempt); // $delay is equal to 3.2 seconds
 
?>

A proof of concept user-land implementation is as follows. This implementation is non-authoritative and may contain bugs.

proof_of_concept.php

<?php
 
namespace Time;
 
class TimeException extends \Exception { }
 
/**
 * Represents a “stop-watch” or “egg-timer” duration as an abstraction over a number
 * of (fractional) seconds with nanosecond precision. It is unaffected by any timezones
 * or “time and date” as shown on a clock.
 *
 * The maximum representable range is 9223372035999999999 nanoseconds (roughly 292 years).
 * Any operation that will overflow, will throw a Time\TimeException.
 *
 * @strict-properties
 */
final readonly class Duration
{
    private function __construct(
        public readonly int $seconds,
        public readonly int $nanoseconds,
        public readonly bool $negative,
    ) {
        if ($seconds > 9_223_372_035) {
            throw new TimeException('The maximum representable range is 9_223_372_035 seconds (roughly 292 years)');
        }
 
        \assert($seconds >= 0);
        \assert($nanoseconds >= 0);
        \assert($nanoseconds < 1_000_000_000);
        \assert($seconds > 0 || $nanoseconds > 0 || !$negative);
    }
 
    /**
     * Create a duration representing $seconds seconds and $nanoseconds nanoseconds. Neither parameter
     * may be negative. $nanoseconds must be less than 1_000_000_000 (the number of nanoseconds in a
     * second).
     *
     * This contructor creates a Duration from its “atomic” components.
     */
    public static function fromSeconds(int $seconds, int $nanoseconds = 0): self
    {
        if ($seconds < 0) {
            throw new \ValueError('$seconds must not be negative');
        }
        if ($nanoseconds < 0 || $nanoseconds >= 1_000_000_000) {
            throw new \ValueError('$nanoseconds must be between 0 and 999_999_999');
        }
 
        return new self($seconds, $nanoseconds, false);
    }
 
    /**
     * Create a duration representing $nanoseconds nano-seconds. $nanoseconds must not be negative.
     */
    public static function fromNanoseconds(int $nanoseconds): self
    {
        $seconds = \intdiv($nanoseconds, 1_000_000_000);
        $nanoseconds = $nanoseconds % 1_000_000_000;
 
        return self::fromSeconds($seconds, $nanoseconds);
    }
 
    /**
     * Create a duration representing $microseconds micro-seconds. $microseconds must not be negative.
     */
    public static function fromMicroseconds(int $microseconds): self
    {
        return self::fromNanoseconds($microseconds * 1_000);
    }
 
    /**
     * Create a duration representing $milliseconds milli-seconds. $milliseconds must not be negative.
     */
    public static function fromMilliseconds(int $milliseconds): self
    {
        return self::fromMicroseconds($milliseconds * 1_000);
    }
 
    /**
     * Create a duration representing $minutes minutes. $minutes must not be negative.
     */
    public static function fromMinutes(int $minutes): self
    {
        return self::fromSeconds($minutes * 60);
    }
 
    /**
     * Create a duration representing $hours hours. $hours must not be negative.
     */
    public static function fromHours(int $hours): self
    {
        return self::fromMinutes($hours * 60);
    }
 
    /**
     * Parse a ISO-8601 period. ISO-8601 periods with a date component will be rejected.
     * The biggest allowed component is H.
     */
    public static function fromIso8601String(string $specification): self
    {
        /* Omitted */
    }
 
    /**
     * Negates the duration.
     *
     * @return self -$this
     */
    public function negate(): self
    {
        if ($this->seconds === 0 && $this->nanoseconds === 0) {
            return $this;
        }
 
        return clone($this, ['negative' => !$this->negative]);
    }
 
    /**
     * Add the given duration to the duration.
     *
     * @return self $this + $duration
     */
    public function add(self $duration): self
    {
        /* (+x) + (-y) == (+x) - (+y) */
        if (!$this->negative && $duration->negative) {
            return $this->sub($duration->negate());
        }
        /* (-x) + (+y) == (+y) - (+x) */
        if ($this->negative && !$duration->negative) {
            return $duration->sub($this->negate());
        }
        /* (-x) + (-y) = -((+x) + (+y))  */
        if ($this->negative && $duration->negative) {
            return $this->negate()->add($duration->negate())->negate();
        }
 
        \assert(!$this->negative);
        \assert(!$duration->negative);
 
        $seconds = $this->seconds + $duration->seconds;
        $nanoseconds = $this->nanoseconds + $duration->nanoseconds;
 
        $seconds += \intdiv($nanoseconds, 1_000_000_000);
        $nanoseconds = $nanoseconds % 1_000_000_000;
 
        return self::fromSeconds($seconds, $nanoseconds);
    }
 
    /**
     * Subtract the given duration from the duration.
     *
     * @return self $this - $duration
     */
    public function sub(self $duration): self
    {
        /* (+x) - (-y) == (+x) + (+y) */
        if (!$this->negative && $duration->negative) {
            return $this->add($duration->negate());
        }
        /* (-x) - (+y) == -((+x) + (+y)) */
        if ($this->negative && !$duration->negative) {
            return $this->negate()->add($duration)->negate();
        }
        /* (-x) - (-y) == (-x) + (+y) */
        if ($this->negative && $duration->negative) {
            return $this->add($duration->negate());
        }
 
        \assert(!$this->negative);
        \assert(!$duration->negative);
 
        if (self::compare($this, $duration) >= 0) {
            $seconds = $this->seconds - $duration->seconds;
            $nanoseconds = $this->nanoseconds - $duration->nanoseconds;
            if ($nanoseconds < 0) {
                $nanoseconds += 1_000_000_000;
                $seconds--;
            }
 
            return self::fromSeconds($seconds, $nanoseconds);
        } else {
            /* (+x) - (+y) = -((+y) - (+x)) */
            return $duration->sub($this)->negate();
        }
    }
 
    /**
     * Multiply the length of the duration by the given factor. $factor must not be negative.
     * 
     * @return self $this * $factor
     */
    public function multiplyBy(int $factor): self
    {
        if ($factor < 0) {
            throw new \ValueError('$factor must not be negative');
        }
 
        $seconds = $this->seconds * $factor;
        $nanoseconds = $this->nanoseconds * $factor;
 
        $seconds += \intdiv($nanoseconds, 1_000_000_000);
        $nanoseconds = $nanoseconds % 1_000_000_000;
 
        return new self($seconds, $nanoseconds, negative: $this->negative);
    }
 
    /**
     * Divide the length of the duration by the given divisor. $divisor must be positive.
     *
     * Fractional nanoseconds will be truncated.
     *
     * @return self $this / $factor
     */
    public function divideBy(int $divisor): self
    {
        if ($divisor <= 0) {
            throw new \ValueError('$divisor must be positive');
        }
 
        $seconds = \intdiv($this->seconds, $divisor);
        $nanoseconds = $this->nanoseconds + (($this->seconds % $divisor) * 1_000_000_000);
        $nanoseconds = \intdiv($nanoseconds, $divisor);
 
        return new self($seconds, $nanoseconds, negative: $this->negative);
    }
 
    /**
     * Returns -1, 0, 1 if $a is less than, equal to, or greater than $b respectively.
     */
    public static function compare(self $a, self $b): int
    {
        if ($a->negative && !$b->negative) {
            return -1;
        }
        if (!$a->negative && $b->negative) {
            return 1;
        }
 
        if ($a->negative && $b->negative) {
            return - ($a->seconds <=> $b->seconds) ?: - ($a->nanoseconds <=> $b->nanoseconds);
        }
 
        if (!$a->negative && !$b->negative) {
            return ($a->seconds <=> $b->seconds) ?: ($a->nanoseconds <=> $b->nanoseconds);
        }
 
        throw new \Error('unreachable');
    }
}

Backward Incompatible Changes

This RFC is introducing a single class and starts using the Time for PHP’s standard library. Adding new symbols is not considered a breaking change as per our policy. The naming of the class and namespace is in line with PHP’s naming policy.

A GitHub search for language:php “namespace Time;” symbol:Duration reveals a total of 7 hits. There are two notable hits with:

which both try to solve the same problem in a very similar way and confirming there is an interest in having this API.

Proposed PHP Version(s)

Next minor (8.6).

RFC Impact

To the Ecosystem

None.

To Existing Extensions

Existing extensions may want to start using this new class where-ever a duration is required.

To SAPIs

None.

Open Issues

None.

Future Scope

The introduction of this class and the associated Time namespace is intended to lay the groundwork for a new date and time library in upcoming PHP versions. It is intentionally designed with a minimal, but useful, API that future additions will be able to build on.

Some ideas that have been taken into account when designing the Time\Duration class:

  • Calculating the difference between two points in time (“Instant”) will return a Time\Duration object.
  • Calendar-based calculations with units larger than one hour (days, weeks, months) will use a dedicated class that only works with a full DateTime carrying both a time and date and a timezone. It will be possible to construct such a “calendar interval” from a Time\Duration, but not the other way around.
  • There are two possible division operations on Durations: Duration by scalar and Duration by Duration. The naming of Duration by scalar was carefully selected to allow Duration by Duration (“divide into”) as future scope.

Additional classes will be added to the exception hierarchy when other classes are added (e.g. TimeOverflowException or DurationException).

Voting Choices

Primary Vote requiring a 2/3 majority to accept the RFC:

Vote: Implement the Time\Duration class as outlined in the RFC? — Yes: 35 · No: 1 · Abstain: 2 (closed)

Secondary Vote to decide whether the “mathematical operation methods” should use full or abbreviated names. This vote is weighted and requires a 2/3 supermajority for abbreviated names to be selected.

Vote: Should the mathematical operation methods of Time\Duration use full or abbreviated names? — multiplyBy, divideBy, negate, absolute: 30 · mul, divBy, neg, abs: 2 · Abstain: 3 (closed)

Patches and Tests

Implementation

References

Rejected Features

  1. Adding a “unit” enum with a single constructor instead of multiple named constructors.
  2. Adding constructors with multiple (named) parameters, such as “hoursAndMinutes”. The fromSeconds() constructor is an intentional exception, because it works with the two “base units”.

Changelog

  • 2026-07-03: Fix mistake proof-of-concept implementation.
  • 2026-07-03: Add secondary vote for naming of the mathematical operations.
  • 2026-06-23: Clarify that every overflow will throw TimeException.
  • 2026-06-23: Add ->absolute().
  • 2026-06-23: Rename ->fromIso8601String() to ->fromIso8601DurationString().
  • 2026-06-23: Limit seconds to 9_223_372_035 to enable possible future scope.
  • 2026-06-23: Add TimeException.
  • 2026-06-22: Clarify that the target API will be responsible for rounding if it cannot deal with nanosecond precision.
  • 2026-06-22: Clarify that non-comparison operators will not be overloaded.
  • 2026-06-18: Initial version.