This is from Text::XSprintf that I've had to put on the back burner. The $mode and stuff is for that module, and the sub below _duration is meant to be called by autogenerated code....
my %Times=(
1 => 'sec|second',
60 => 'min|minute',
60*60 => 'hour',
60*60*24 => 'day',
60*60*24*365 => 'year'
);
sub _dstr{
my ($mult,$mode,$unit)=@_;
my $str=$mult;
if ($mode!~/^[h#]/) {
my @names=split /\|/,$Times{$unit};
$str.=($mode eq 'l' ? " $names[-1]" : " $names[0]");
$str.="s" if $mult!=1;
} elsif ($mode eq 'h') {
$str.=substr($Times{$unit},0,1);
}
return $str
}
sub _duration {
my $mode=lc(shift); #
my $dur=shift;
$mode=~/^[hml#]$/ or $mode="m";
my $negative=$dur<0 ? ($mode eq "l" ? "negative " : $mode eq "m" ?
+ "neg " : "-")
: "";
my @units;
foreach my $unit (sort {$b <=> $a} keys %Times) {
next unless $unit>1;
if ($dur>=$unit) {
my $mult=int($dur/$unit);
$dur-=$mult*$unit;
push @units,_dstr $mult,$mode,$unit;
} elsif ($mode eq "#" and @units) {
push @units,0;
}
}
if ($dur or $mode eq "#" or not @units) {
push @units,_dstr $dur,$mode,1;
}
$units[-2].=" and ".pop @units
if @units>1 and $mode eq 'l';
return $mode ne "#" ? $negative.join( ", ",@units)
: $negative.sprintf(join(":",("%02d") x @units
+),@units);
}
Anyway, I figured this was similar to some of your stuff and you did mention being curious as to how others have done stuff....
---
demerphq
<Elian> And I do take a kind of perverse pleasure in having an OO assembly language...