Greetings, Fellow Monks.
I have recently put the finishing touches on a module that formats integers into durations. So something like "3661" becomes "1 hour, 1 minute" (or, if a different option is passed in, it becomes "1 hour, 1 minute, 1 second").
## Luke Hutscal
## Started November 12 2007
## Finished November 13 or so.
## Added display order setting on the 14th.
package My::Module;
use 5.008008;
use strict;
use warnings;
our $VERSION = '0.04';
# Preloaded methods go here.
## These are my local subs
## users should not be able to get at them.
my $processInterval = sub {
my $self = shift;
my($var,$plural,$singular) = @$_;
if($var > 0) {
my %entry;
$entry{value} = $var;
$entry{word} = $var > 1 ? $self->{$plural} : $self->{$singular
+};
return \%entry;
}
return undef;
};
sub new {
my $self = shift;
my $defaults = {};
## here we set the default values for our module.
%$defaults = (
second => 'second',
seconds => 'seconds',
minute => 'minute',
minutes => 'minutes',
hour => 'hour',
hours => 'hours',
day => 'day',
days => 'days',
week => 'week',
weeks => 'weeks',
month => 'month',
months => 'months',
year => 'year',
years => 'years',
display => 2, # This is how many are displayed b
+y default
order => 'desc', # this is the order things are disp
+layed in
@_ # load in all the options passed to
+us
);
bless $defaults, $self;
}
sub parse_seconds {
my $self = shift;
my $seconds = shift;
my $display = shift;
my $parsed;
my($minutes,$hours,$days,$weeks,$years);
## We don't have any months because it's harder - 12 months, but 5
+2 weeks makes for 13. See?
# minutes
$minutes = int($seconds/60);
$seconds-=$minutes*60;
# hours
$hours = int($minutes/60);
$minutes-=$hours*60;
# days
$days = int($hours/24);
$hours-=$days*24;
# weeks
$weeks = int($days/7);
$days-=$weeks*7;
# years
$years = int($weeks/52);
$weeks-=$years*52;
my @output;
## We add our intervals in this order, so that we can have output
+show up from largest to smallest.
my @intervals = (
[$years,'years','year'],
[$weeks,'weeks','week'],
[$days,'days','day'],
[$hours,'hours','hour'],
[$minutes,'minutes','minute'],
[$seconds,'seconds','second'],
);
# By default, we're displaying in descending order. However, if th
+e user has specified
# ascending order, we reverse the order we'll be handling our arra
+y in.
## This is done with a regex so that users can supply "asc", "asce
+nd", "ascending", and still have
## everything work properly.
if ($self->{order} =~ /^asc/) {
@intervals = reverse @intervals;
}
# thanks Andrew!
@output = grep {defined} map { $processInterval->($self,$_) } @int
+ervals;
for(my $i = 0; $i < ($display ? $display : $self->{display}) && $i
+ < @output; $i++) {
## padding our output
my $padding = $i > 0 ? ' ' : '';
my $ending = ($i < ($display ? ($display-1) : ($self->{display
+}-1))) && ($i < (@output-1)) ? ',' : '';
$parsed .= $padding . $output[$i]->{'value'} . ' ' . $output[
+$i]->{'word'} . $ending;
}
return $parsed;
}
1;
And I can't figure out what to call my module. The best recommendation I've heard is DateTime::NaturalLanguage - but after discussing it on the mailing lists, I don't get the feeling that it really falls under the DateTime namespace. Does anyone have a recommendation on what to call my module?