NAME

Time::Keeper::Duration - an amount of time: months, days, minutes and seconds

VERSION

Version 0.01

SYNOPSIS

use Time::Keeper;

my $d = Time::Keeper::Duration->new(months => 1, days => 2, hours => 3);
my $t = Time::Keeper->now->plus($d);
my $u = Time::Keeper->now + $d;

my $between = $b - $a;              # a duration
print $between->days, "\n";
print "$between\n";                 # P1M2DT3H, ISO 8601

my $ninety = Time::Keeper::Duration->from_seconds(90);
print $ninety->total_seconds, "\n"; # 90

DESCRIPTION

A duration is an amount of time in four units that do not turn into one another: months, because a month is not a fixed number of days; days, because a day is not always 24 hours where the clocks change; minutes, because a minute is not always 60 seconds when there is a leap second; and seconds, with nanoseconds. Years are kept as months, weeks as days and hours as minutes.

Each unit has its own sign, so a duration can be a month forward and a day back. Durations, like Time::Keeper values, never change: every method that would change one returns a new one.

How a duration is added to a time is described under "ARITHMETIC" in Time::Keeper.

CONSTRUCTORS

new

my $d = Time::Keeper::Duration->new(
    years => 1, months => 2, weeks => 3, days => 4,
    hours => 5, minutes => 6, seconds => 7, nanoseconds => 8,
    end_of_month => 'limit',
);

Every unit is optional and a whole number; nanoseconds past a second are carried into the seconds exactly. end_of_month is wrap, limit or preserve, as described under "Months and the end of the month" in Time::Keeper.

from_seconds

my $d = Time::Keeper::Duration->from_seconds(90);
my $d = Time::Keeper::Duration->from_seconds('1.000000001');

A duration of seconds alone. A string of digits with up to nine decimal places is taken exactly; a number with a fraction is rounded to the microsecond.

parse

my $d = Time::Keeper::Duration->parse('P1Y2M3DT4H5M6.5S');

An ISO 8601 duration: P, then years, months, weeks and days, then T and hours, minutes and seconds, any of them left out, and - before it for a negative one. The last of the hours, minutes or seconds may have a fraction: PT1.5H is an hour and 30 minutes. A part may have a sign of its own, as "iso8601" writes a duration whose parts differ in sign.

THE UNITS

As DateTime::Duration gives them: each is the size of its part, never negative, so a duration of 90 minutes is 1 hour and 30 minutes.

years

months

The whole years in the months, and the months left over.

weeks

days

The whole weeks in the days, and the days left over.

hours

minutes

The whole hours in the minutes, and the minutes left over.

seconds

nanoseconds

in_units

my ($h, $m) = $d->in_units('hours', 'minutes');

The duration in the units asked for, with signs. Each unit takes what it can from its own part, the larger units first: years and months from the months, weeks and days from the days, hours and minutes from the minutes, seconds and nanoseconds from the seconds. A unit never borrows from another part, since months, days and minutes do not convert. In scalar context, the first unit asked for.

deltas

The five parts as a list of pairs: months, days, minutes, seconds and nanoseconds.

end_of_month

wrap, limit or preserve.

is_positive

is_negative

is_zero

True when every part is zero or more and one is more than zero; when every part is zero or less and one is less; or when every part is zero. A duration with parts of both signs is neither positive nor negative.

total_seconds

The duration as a number of seconds, for one with no months or days: those are not a fixed number of seconds, and a duration with them is an error here.

NEW DURATIONS FROM OLD

inverse

The duration with every part's sign turned over. Its end_of_month is worked out afresh for its new months unless given: $d->inverse(end_of_month => 'limit').

calendar_duration

clock_duration

The months and days alone, and the minutes and seconds alone.

plus

minus

$d->plus($e) and $d->minus($e): part by part. + and - are the same, and -$d is "inverse".

multiply

$d->multiply(3): every part three times, as $d * 3. The factor is a whole number.

COMPARING AND PRINTING

compare

Time::Keeper::Duration->compare($d, $e);
Time::Keeper::Duration->compare($d, $e, $start);

-1, 0 or 1 as $d is shorter than, as long as or longer than $e, measured from $start, or from now. A month is longer from 1 January than from 1 February, so durations with months or days compare only from a starting point: <=> compares durations without them, and is an error for those with.

iso8601

The ISO 8601 form, such as P1Y2M3DT4H5M6.5S, as "$d" gives it. A duration whose parts have both signs has no ISO 8601 form; each part is then given with its own sign, as P1M-2D.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)