Date-Span
view release on metacpan or search on metacpan
lib/Date/Span.pm view on Meta::CPAN
use strict;
use warnings;
package Date::Span 1.129;
# ABSTRACT: deal with date/time ranges than span multiple dates
use Exporter;
BEGIN { our @ISA = 'Exporter' }
our @EXPORT = qw(range_expand range_durations range_from_unit); ## no critic
#pod =head1 SYNOPSIS
#pod
#pod use Date::Span;
#pod
#pod @spanned = range_expand($start, $end);
#pod
#pod print "from $_->[0] to $_->[1]\n" for (@spanned);
#pod
#pod =head1 DESCRIPTION
#pod
#pod This module provides code for dealing with datetime ranges that span multiple
#pod calendar days. This is useful for computing, for example, the amount of
#pod seconds spent performing a task on each day. Given the following table:
#pod
#pod event | begun | ended
#pod ---------+------------------+------------------
#pod loading | 2004-01-01 00:00 | 2004-01-01 12:45
#pod venting | 2004-01-01 12:45 | 2004-01-02 21:15
#pod running | 2004-01-02 21:15 | 2004-01-03 00:00
#pod
#pod We may want to gather the following data:
#pod
#pod date | event | time spent
#pod ------------+---------+----------------
#pod 2004-01-01 | loading | 12.75 hours
#pod 2004-01-01 | venting | 11.25 hours
#pod 2004-01-02 | venting | 21.25 hours
#pod 2004-01-02 | running | 2.75 hours
#pod
#pod Date::Span takes a data like the first and produces data more like the second.
#pod (Details on exact interface are below.)
#pod
#pod =func range_durations
#pod
#pod my @durations = range_durations($start, $end)
#pod
#pod Given C<$start> and C<$end> as timestamps (in epoch seconds),
#pod C<range_durations> returns a list of arrayrefs. Each arrayref is a date
#pod (expressed as epoch seconds at midnight) and the number of seconds for which
#pod the given range intersects with the date.
#pod
#pod =cut
sub _date_time {
my $date = $_[0] - (my $time = $_[0] % 86400);
($date, $time)
}
sub range_durations {
my ($start, $end) = @_;
return if $end < $start;
my ($start_date, $start_time) = _date_time($start);
my ($end_date, $end_time) = _date_time($end);
push my @results, [
$start_date,
(( $end_date != $start_date ) ? ( 86400 - $start_time ) : ($end - $start))
];
push @results,
map { [ $start_date + 86400 * $_, 86400 ] }
(1 .. ($end_date - $start_date - 86400) / 86400)
if ($end_date - $start_date > 86400);
push @results, [ $end_date, $end_time ] if $start_date != $end_date;
return @results;
}
#pod =func range_expand
#pod
lib/Date/Span.pm view on Meta::CPAN
Time::Local::timegm(
0, # $sec
$_[4]||0, # $min
$_[3]||0, # $hour
$_[2]||1, # $mday
$_[1]||0, # $mon
$_[0] # $year
);
}
sub range_from_unit {
my $code = (ref($_[-1])||'' eq 'CODE') ? pop : \&_begin_secs;
return unless @_;
my ($year,$month,$day,$hour,$min) = @_;
my $begin_secs = $code->(@_);
my $length = defined $min ? 60
: defined $hour ? 3600
: defined $day ? 86400
: defined $month ? 86400 * $monthdays[$month+0]
+ _leap_secs($year, $month)
: 86400 * (_is_leap($year) ? 366 : 365);
return ($begin_secs, $begin_secs + $length - 1);
}
#pod =head1 TODO
#pod
#pod This code was just yanked out of a general purpose set of utility functions
#pod I've compiled over the years. It should be refactored (internally) and
#pod further tested. The interface should stay pretty stable, though.
#pod
#pod =cut
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Date::Span - deal with date/time ranges than span multiple dates
=head1 VERSION
version 1.129
=head1 SYNOPSIS
use Date::Span;
@spanned = range_expand($start, $end);
print "from $_->[0] to $_->[1]\n" for (@spanned);
=head1 DESCRIPTION
This module provides code for dealing with datetime ranges that span multiple
calendar days. This is useful for computing, for example, the amount of
seconds spent performing a task on each day. Given the following table:
event | begun | ended
---------+------------------+------------------
loading | 2004-01-01 00:00 | 2004-01-01 12:45
venting | 2004-01-01 12:45 | 2004-01-02 21:15
running | 2004-01-02 21:15 | 2004-01-03 00:00
We may want to gather the following data:
date | event | time spent
------------+---------+----------------
2004-01-01 | loading | 12.75 hours
2004-01-01 | venting | 11.25 hours
2004-01-02 | venting | 21.25 hours
2004-01-02 | running | 2.75 hours
Date::Span takes a data like the first and produces data more like the second.
(Details on exact interface are below.)
=head1 PERL VERSION
This library should run on perls released even a long time ago. It should work
on any version of perl released in the last five years.
Although it may work on older versions of perl, no guarantee is made that the
minimum required version will not be increased. The version may be increased
for any reason, and there is no promise that patches will be accepted to lower
the minimum required perl.
=head1 FUNCTIONS
=head2 range_durations
my @durations = range_durations($start, $end)
Given C<$start> and C<$end> as timestamps (in epoch seconds),
C<range_durations> returns a list of arrayrefs. Each arrayref is a date
(expressed as epoch seconds at midnight) and the number of seconds for which
the given range intersects with the date.
=head2 range_expand
my @endpoint_pairs = range_expand($start, $end);
Given C<$start> and C<$end> as timestamps (in epoch seconds),
C<range_durations> returns a list of arrayrefs. Each arrayref is a start and
end timestamp. No pair of start and end times will cross a date boundary, and
the set of ranges as a whole will be identical to the passed start and end.
=head2 range_from_unit
my ($start, $end) = range_from_unit(@date_unit)
C<@date_unit> is a specification of a unit of time, in the form:
@date_unit = ($year, $month, $day, $hour, $minute);
Only C<$year> is mandatory; other arguments may be added, in order. Month is
given in the range (0 .. 11). This function will return the first and last
( run in 2.028 seconds using v1.01-cache-2.11-cpan-99c4e6809bf )