Hi all,
I made a new module to calculate time duration. My module differs from
DateTime::Duration because it is not dealing with dates. It
does not try to foresee which is a future of past date based in a bunch of seconds.
It just provide a means to calculate a "time quantity" that is more human readable
than a big number of seconds.
For example, if you're making a big file transfer over the network everyday, and this
transfer takes 7341 seconds to finish, and you
want to receive a report saying how much time the transfer took, indeed, you want to
know that the file transfer took 2 hours, 2
minutes and 21 seconds (7341 seconds "grouped by" hours).
My module will calculate this conversion of seconds to a bigger "time group", HOURS,
in this case.
To do this with my module you would:
# - converting seconds to hours -
new $time = new Time::Seconds::GroupedBy('HOURS');
my ($secs, $mins, $hours) = $time->calculate(7341);
print "$hours hours $mins minutes $secs seconds\n";
So, if you have more seconds to calculate, maybe hours is a small quantity, then you
may chose to group seconds in a bigger group,
like DAYS. For example, to know that 734100 seconds are equivalent to 8 days, 11
hours, 55 mins, 0 seconds.
# - converting seconds to days -
$time->groubBy('DAYS');
my ($secs, $mins, $hours, $days) = $time->calculate(734100);
When "DAYS" is a small group, you could group them by "MONTHS", ultimately, by "YEARS".
Also, i could add a setting like "AUTO" in which it would choose the most apropriate
time grouping based on the amount of seconds
received.
Its draft source is bellow:
package GroupedBy;
use strict;
sub new {
my $class = shift;
my $self = {};
bless ( $self, $class );
my $GroupedBy = shift;
# Amount of Seconds input by the user (set by calculate() method)
$self->{SECONDS};
# Initializing data about years, months, days, hours and minutes;
$self->{SECS} = { result => 0 };
# A minute is 60 seconds
$self->{MINS} = { inSecs => 60, opId => 1, took => 0, result => 0 };
# An hour is 60 * 60 seconds
$self->{HOURS} = { inSecs => 3600, opId => 2, took => 0, result => 0 };
# A day is 60 * 60 * 24 seconds
$self->{DAYS} = { inSecs => 86400, opId => 3, took => 0, result => 0 };
# A month is 60 * 60 * 24 * 30 seconds
$self->{MONTHS} = { inSecs => 2592000, opId => 4, took => 0, result => 0 };
# Year is 60 * 60 * 24 * 365.24225 = 31556930.4 seconds (we'll ignore 0.4 secs)
$self->{YEARS} = { inSecs => 31556930, opId => 5, took => 0, result => 0 };
# OPID - operation ID, is a number indentifying the kind of grouping that
# was chosen by the user. Each grouping requires a diferent operation to
# calculate the resulting values.
$self->{OPID} = $self->{$GroupedBy}->{opId};
die "Unvalid value. Valid values are 'MINS', 'HOURS', 'DAYS', 'MONTHS', 'YEARS'"
unless defined $self->{OPID};
return $self;
}
sub calculate { # returns: Array: the results of the calculus
my $self = shift;
$self->{SECONDS} = shift;
$self->_clean();
my @result = ( $self->_years(), $self->_months(), $self->_days(),
$self->_hours(), $self->_mins(), $self->_secs() );
return reverse @result;
}
sub groupedBy { # returns: String: the current GROUPED_BY type
my $self = shift;
my $GroupedBy = shift;
$self->{OPID} = undef; # cleans current value
$self->{OPID} = $self->($GroupedBy)->{opId};
die "Unvalid value. Valid values are 'MINS', 'HOURS', 'DAYS', 'MONTHS', 'YEARS'"
unless defined $self->{OPID};
return $GroupedBy;
}
# Cleans(set to 0)the 'took' and 'result' counters for all groups
sub _clean { # returns: nothing
my $self = shift;
foreach ( qw ( SECS MINS HOURS DAYS MONTHS YEARS ) ) {
$self->{$_}->{took} = 0;
$self->{$_}->{result} = 0;
}
}
sub _secs { # returns: Integer: the result
my $self = shift;
my $name = "SECS";
$self->{$name}->{result} = $self->{SECONDS} - $self->{YEARS}->{took}
- $self->{MONTHS}->{took} - $self->{DAYS}->{took} - $self->{HOURS}->{took}
- $self->{MINS}->{took};
return $self->{$name}->{result};
}
sub _mins { # returns: Integer: the result
my $self = shift;
my $name = "MINS";
if ( $self->{OPID} >= 1 ) {
my $secsLeft = $self->{SECONDS} - $self->{YEARS}->{took}
- $self->{MONTHS}->{took} - $self->{DAYS}->{took} - $self->{HOURS}->{took};
$self->{$name}->{result} = int($secsLeft / $self->{$name}->{inSecs});
if ( $self->{$name}->{result} != 0 ) {
$self->{$name}->{took} = $self->{$name}->{result} * $self->{$name}->{inSecs};
}
}
return $self->{$name}->{result};
}
sub _hours { # returns: Integer: the result
my $self = shift;
my $name = "HOURS";
if ( $self->{OPID} >= 2 ) {
my $secsLeft = $self->{SECONDS} - $self->{YEARS}->{took}
- $self->{MONTHS}->{took} - $self->{DAYS}->{took};
$self->{$name}->{result} = int($secsLeft / $self->{$name}->{inSecs});
if ( $self->{$name}->{result} != 0 ) {
$self->{$name}->{took} = $self->{$name}->{result} * $self->{$name}->{inSecs};
}
}
return $self->{$name}->{result};
}
sub _days { # returns: Integer: the result
my $self = shift;
my $name = "DAYS";
if ( $self->{OPID} >= 3 ) {
my $secsLeft = $self->{SECONDS} - $self->{YEARS}->{took} - $self->{MONTHS}->{took};
$self->{$name}->{result} = int($secsLeft / $self->{$name}->{inSecs});
if ( $self->{$name}->{result} != 0 ) {
$self->{$name}->{took} = $self->{$name}->{result} * $self->{$name}->{inSecs};
}
}
return $self->{$name}->{result};
}
sub _months { # returns: Integer: the result
my $self = shift;
my $name = "MONTHS";
if ( $self->{OPID} >= 4 ) {
my $secsLeft = $self->{SECONDS} - $self->{YEARS}->{took};
$self->{$name}->{result} = int($secsLeft / $self->{$name}->{inSecs});
if ( $self->{$name}->{result} != 0 ) {
$self->{$name}->{took} = $self->{$name}->{result} * $self->{$name}->{inSecs};
}
}
return $self->{$name}->{result};
}
sub _years { # returns: Integer: the result
my $self = shift;
my $name = "YEARS";
if ( $self->{OPID} == 5 ) {
$self->{$name}->{result} = int($self->{SECONDS} / $self->{$name}->{inSecs});
if ( $self->{$name}->{result} != 0 ) {
$self->{$name}->{took} = $self->{$name}->{result} * $self->{$name}->{inSecs};
}
}
return $self->{$name}->{result};
}
What do you think about it?
Do you think this module is doing something you're not doing yet? Is it really
different from DateTime::Duration? (at least, it is
easier to use...)
A hug for everybody,
bruno negr�o.