Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

RFC: My duration-formatting module

by Spidy (Chaplain)
on Feb 13, 2008 at 04:43 UTC ( #667727=perlmeditation: print w/replies, xml ) Need Help??

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").

This is the code:

## 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?



Replies are listed 'Best First'.
Re: RFC: My duration-formatting module
by grinder (Bishop) on Feb 13, 2008 at 07:04 UTC

    In what way is your module different from Time::Duration? At a glance, it appears to do pretty much the same thing.

    • another intruder with the mooring in the heart of the Perl

Re: RFC: My duration-formatting module
by Limbic~Region (Chancellor) on Feb 13, 2008 at 13:45 UTC
    use 5.008008; Why?

    As has been mentioned by others, there are a few modules that perform a similar function. When I was playing with this idea (see RFC: Seconds2English for details), it was a toy project to learn. I do remember adding features that were not in any of the CPAN modules available at the time, but now I don't remember what they are. Here is my recommendation:

    Find one or more features not provided by the existing modules and provide a patch to the author. If the author is unreceptive and the module is OO, then subclass and post on CPAN. If the module is not OO and you feel these features still warrant addition to CPAN, then put up your own module but be sure to include in the POD the distinction between the modules so that folks can choose for themselves.

    Cheers - L~R

Re: RFC: My duration-formatting module
by mr_mischief (Monsignor) on Feb 14, 2008 at 18:54 UTC
    This might sound like it's coming from nowhere, but your module belongs nowhere more than in the Lingua::EN namespace. Perhaps Lingua::EN::Time::Duration would work.

    Let me explain. Your module is, after all, Anglocentric. A module in DateTime or other general-purpose namspaces in my opinion should not be so centered on a single natural language. I certainly wouldn't want to use an application library that only accounted for Brazilian Portuguese users or Chinese users that came from a general-purpose repository.

    I think the criteria for putting such a thing in the DateTime namespace should include some more than just working with dates and times. It should be more data-centric, with language definitions that allow one to specify a language and get the duration in that language. If it defaults to English and the only initial language definition is English, those two things wouldn't bother me a bit. However, I think it's pretty arrogant of Anglophones to assume that a general-purpose tool should be built around English as an intimate part of the problem description (and I'm a corn-fed Midwestern guy, so this isn't just some anti-American backlash).

    Alternatively, instead of having a data-centric solution under DateTime, multiple different Lingua::foo::Time::Duration modules could pop up once the theme is set. That would be bad for code reuse, but it would allow each to combine the strings with the code with no problem and also allow any special idea of time we don't understand (half or quarter hours being special, a four-hour watch, etc) to be coded separately. In all, it's probably best to make it based around a language definition and share the code, though. Special cases could be taken care of by subclassing.

    I guess what my point boils down to is that your killer feature that should be offered to an existing module maintainer or used as the justification of a new CPAN module should be natural language independence. I think a DateTime::Duration or DateTime::NaturalLanguage or whatever that is easy to make work with more than one natural language would be a heck of a tool. Time::Duration has already been localized into at least Swedish and Japanese, and it'd be really nice if that could be done without changing strings in the code.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://667727]
Approved by kyle
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2017-06-23 02:26 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (533 votes). Check out past polls.