|
|
| |
DateTime::Format::Duration(3) |
User Contributed Perl Documentation |
DateTime::Format::Duration(3) |
DateTime::Format::Duration - Format and parse DateTime::Durations
use DateTime::Format::Duration;
$d = DateTime::Format::Duration->new(
pattern => '%Y years, %m months, %e days, '.
'%H hours, %M minutes, %S seconds'
);
print $d->format_duration(
DateTime::Duration->new(
years => 3,
months => 5,
days => 1,
hours => 6,
minutes => 15,
seconds => 45,
nanoseconds => 12000
)
);
# 3 years, 5 months, 1 days, 6 hours, 15 minutes, 45 seconds
$duration = $d->parse_duration(
'3 years, 5 months, 1 days, 6 hours, 15 minutes, 45 seconds'
);
# Returns DateTime::Duration object
print $d->format_duration_from_deltas(
years => 3,
months => 5,
days => 1,
hours => 6,
minutes => 15,
seconds => 45,
nanoseconds => 12000
);
# 3 years, 5 months, 1 days, 6 hours, 15 minutes, 45 seconds
%deltas = $d->parse_duration_as_deltas(
'3 years, 5 months, 1 days, 6 hours, 15 minutes, 45 seconds'
);
# Returns hash:
# (years=>3, months=>5, days=>1, hours=>6, minutes=>15, seconds=>45)
This module formats and parses DateTime::Duration objects as well as other
durations representations.
This module contains a single constructor:
- •
- "new( ... )"
The "new" constructor takes
the following attributes:
- "pattern => $string"
This is a strf type pattern detailing the format of the
duration. See the "Patterns" sections below for more
information.
- "normalise =>
$one_or_zero_or_ISO"
- "normalize => $one_or_zero_or_ISO"
This determines whether durations are 'normalised'. For
example, does 120 seconds become 2 minutes?
Setting this value to true without also setting a
"base" means we will normalise without
a base. See the "Normalising without a base" section
below.
- "base => $datetime_object"
If a base DateTime is given then that is the normalisation
date. Setting this attribute overrides the above option and sets
normalise to true.
DateTime::Format::Duration has the following methods:
- "format_duration( $datetime_duration_object
)"
- "format_duration( duration => $dt_duration,
pattern => $pattern )"
Returns a string representing a DateTime::Duration object in
the format set by the pattern. If the first form is used, the pattern is
taken from the object. If the object has no pattern then this method
will croak.
- "format_duration_from_deltas( %deltas
)"
- "format_duration_from_deltas( %deltas, pattern =>
$pattern )"
As above, this method returns a string representing a duration
in the format set by the pattern. However this method takes a hash of
values. Permissible hash keys are "years, months,
days, hours, minutes, seconds" and
"nanoseconds" as well as
"negative" which, if true, inverses
the duration. ("years => -1" is the
same as "years => 1,
negative=>1")
- "parse_duration( $string )"
This method takes a string and returns a DateTime::Duration
object that is the equivalent according to the pattern.
- "parse_duration_as_deltas( $string )"
Once again, this method is the same as above, however it
returns a hash rather than an object.
- "normalise( $duration_object )"
- "normalize( %deltas )"
Returns a hash of deltas after normalising the input. See the
"NORMALISE" section below for more information.
- "pattern()"
Returns the current pattern.
- "base()"
Returns the current base.
- "normalising()"
Indicates whether or not the durations are being
normalised.
All setters return the object so that they can be strung together.
- "set_pattern( $new_pattern )"
Sets the pattern and returns the object.
- "set_base( $new_DateTime )"
Sets the base DateTime and returns the object.
- "set_normalising( $true_or_false_or_ISO
)"
Turns normalising on or off and returns the object.
This module uses a similar set of patterns to strftime. These patterns have been
kept as close as possible to the original time-based patterns.
- %C
The number of hundreds of years in the duration. 400 years
would return 4. This is similar to centuries.
- %d
The number of days zero-padded to two digits. 2 days returns
02. 22 days returns 22 and 220 days returns 220.
- %e
The number of days.
- %F
Equivalent of %Y-%m-%d
- %H
The number of hours zero-padded to two digits.
- %I
Same as %H
- %j
The duration expressed in whole days. 36 hours returns 1
- %k
The hours without any padding
- %l
Same as %k
- %m
The months, zero-padded to two digits
- %M
The minutes, zero-padded to two digits
- %n
A linebreak when formatting and any whitespace when
parsing
- %N
Nanoseconds - see note on precision at end
- %p
Either a '+' or a '-' indicating the positiveness of the
duration
- %P
A '-' for negative durations and nothing for positive
durations.
- %r
Equivalent of %H:%M:%S
- %R
Equivalent of %H:%M
- %s
Returns the value as seconds. 1 day, 5 seconds return
86405
- %S
Returns the seconds, zero-padded to two digits
- %t
A tab character when formatting or any whitespace when
parsing
- %T
Equivalent of %P%H:%M:%S
- %u
Days after weeks are removed. 4 days returns 4, but 22 days
returns 1 (22 days is three weeks, 1 day)
- %V
Duration expressed as weeks. 355 days returns 52.
- %W
Duration expressed as floating weeks. 10 days, 12 hours
returns 1.5 weeks.
- %y
Years in the century. 145 years returns 45.
- %Y
Years, zero-padded to four digits
- %%
A '%' symbol
Precision can be changed for any and all the above values.
For all but nanoseconds (%N), the precision is the zero-padding. To change
the precision insert a number between the '%' and the letter. For example: 1
year formatted with %6Y would return 000001 rather
than the default 0001. Likewise, to remove padding
%1Y would just return a 1.
Nanosecond precision is the other way (nanoseconds are fractional
and thus should be right padded). 123456789 nanoseconds formatted with
%3N would return 123 and formatted as
%12N would return 123456789000.
This module contains a complex method for normalising durations. The method
ensures that the values for all components are as close to zero as possible.
Rather than returning 68 minutes, it is normalised to 1 hour, 8 minutes.
The complexity comes from three places:
- Mixed positive and negative components
The duration of 1 day, minus 2 hours is easy to normalise in
your head to 22 hours. However consider something more complex such as
-2 years, +1 month, +22 days, +11 hours, -9 minutes.
This module works from lowest to highest precision to
calculate the duration. So, based on a
"base" of 2004-03-28T00:00:00 the
following transformations take place:
2003-01-01T00:00:00 - 2 years = 2001-01-01T00:00:00 === -2 years
2001-01-01T00:00:00 + 1 month = 2001-02-01T00:00:00 === -1 year, 11 months
2001-02-01T00:00:00 + 22 days = 2001-02-23T00:00:00 === -1yr, 10mths, 6days
2001-02-22T00:00:00 + 11 hours = 2001-02-23T11:00:00 === -1y, 10m, 6d, 13h
2001-02-22T11:00:00 - 9 minutes = 2001-02-23T10:51:00 === -1y, 10m, 6d, 13h, 9m
See:
https://raw.githubusercontent.com/karenetheridge/DateTime-Format-Duration/master/docs/figure1.gif
Figure 1 illustrates that, with the given base, -2 years, +1
month, +22 days, +11 hours, -9 minutes is normalised to -1 year, 10
months, 6 days, 13 hours and 9 minutes.
- Months of unequal length.
Unfortunately months can have 28, 29, 30 or 31 days and it can
change from year to year. Thus if I wanted to normalise 2 months it
could be any of 59 (Feb-Mar), 60 (Feb-Mar in a leap year), 61 (Mar-Apr,
Apr-May, May-Jun, Jun-Jul, Aug-Sep, Sep-Oct, Oct-Nov or Nov-Dec) or 62
days (Dec-Jan or Jul-Aug). Because of this the module uses a base
datetime for its calculations. If we use the base 2003-01-01T00:00:00
then two months would be 59 days (2003-03-01 - 2003-01-01)
- The order of components
Components will always be assessed from lowest to highest
precision (years, months, days, hours, minutes, seconds, nanoseconds).
This can really change things.
Consider the duration of 1 day, 24 hours. Normally this will
normalise to 2 days. However, consider changes to Daylight Savings. On
the changes to and from DST days have 25 and 23 hours.
If we take the base DateTime as midnight on the day DST ends
(when there's 25 hours in the day), and add 1 day, 24 hours we end up at
midnight 2 days later. So our duration normalises to two days.
However, if we add 24 hours, 1 day we end up at 11pm on the
next day! Why is this? Because midnight + 24 hours = 11pm (there's 25
hours on this day!), then we add 1 day and end up at 11pm on the
following day. See:
https://raw.githubusercontent.com/karenetheridge/DateTime-Format-Duration/master/docs/figure2.gif
Figure 2 illustrates the above problem on timelines.
- Leap years and leap seconds
Leap years and seconds further add to the confusion in
normalisation. Leap seconds mean there are minutes that are 61 seconds
long, thus 130 seconds can be 2 minutes, 10 seconds or 2 minutes 9
seconds, depending on the base DateTime. Similarly leap years mean a day
can have 23, 24 or 25 hours. See:
https://raw.githubusercontent.com/karenetheridge/DateTime-Format-Duration/master/docs/figure3.gif
Figure 3 shows how leaps are calculated on timelines.
This module includes two ways to normalise without a base.
- Standard Normalisation
Using standard normalisation without a base, 45 days will stay
as 45 days as there is no way to accurately convert to months. However
the following assumptions will be made: There are 24 hours in a day and
there are 60 seconds in a minute.
- ISO Normalisation
In ISO8601v2000, Section 5.5.3.2 says that "The values
used must not exceed the 'carry-over points' of 12 months, 30 days, 24
hours, 60 minutes and 60 seconds". Thus if you set the normalise
option of the constructor, or use set_normalising to 'ISO', months will
be normalised to 30 days.
This module can bypass duration objects and just work with delta hashes. This
used to be of greatest value with earlier versions of DateTime::Duration when
DateTime::Duration assumed a duration with one negative component was a
negative duration (that is, -2 hours, 34 minutes was assumed to be -2 hours,
-34 minutes).
These extra methods have been left in here firstly for
backwards-compatibility but also as an added 'syntactic sugar'. Consider
these two equivalent expressions:
$one = $o->format_duration(
DateTime::Duration->new(
years => -2,
days => 13,
hours => -1
)
);
$two = $o->format_duration_from_deltas(
years => -2,
days => 13,
hours => -1
);
These both create the same string in $one
and $two, but if you don't already have a
DateTime::Duration object, the later looks cleaner.
datetime@perl.org mailing list
http://datetime.perl.org/
Bugs may be submitted through the RT bug tracker
<https://rt.cpan.org/Public/Dist/Display.html?Name=DateTime-Format-Duration>
(or bug-DateTime-Format-Duration@rt.cpan.org
<mailto:bug-DateTime-Format-Duration@rt.cpan.org>).
There is also a mailing list available for users of this
distribution, at <http://lists.perl.org/list/datetime.html>.
I am also usually active on irc, as 'ether' at
"irc.perl.org".
Rick Measham <rickm@cpan.org>
Karen Etheridge <ether@cpan.org>
This software is copyright (c) 2003 by Rick Measham.
This is free software; you can redistribute it and/or modify it
under the same terms as the Perl 5 programming language system itself.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |