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)