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.


Reply via email to