Skip to content

Commit

Permalink
added time_in_words helper
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Aug 28, 2014
1 parent a8aec73 commit 89b101f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 4 deletions.
69 changes: 69 additions & 0 deletions lib/Mojo/Date.pm
Expand Up @@ -73,6 +73,35 @@ sub to_string {
$MONTHS[$month], $year + 1900, $h, $m, $s;
}

sub to_words {
my $self = shift;
my $from = shift // time;

my $s = $from - $self->epoch;
$s = $s * -1 if my $in = $s < 0;
return _wrap($in, 'less than a minute') if $s < 45;
return _wrap($in, 'about a minute') if $s < 90;

my $m = int($s / 60);
return _wrap($in, "$m minutes") if $m < 45;
return _wrap($in, 'about an hour') if $m < 90;

my $h = int($m / 60);
return _wrap($in, "$h hours") if $h < 24;
return _wrap($in, 'a day') if $h < 42;

my $days = int($h / 24);
return _wrap($in, "$days days") if $days < 30;
return _wrap($in, 'about a month') if $days < 45;
return _wrap($in, "@{[int($days / 30)]} months") if $days < 365;

my $years = $days / 365;
return _wrap($in, 'about a year') if $years < 1.5;
return _wrap($in, "@{[int $years]} years");
}

sub _wrap { $_[0] ? "in $_[1]" : "$_[1] ago" }

1;

=encoding utf8
Expand Down Expand Up @@ -170,6 +199,46 @@ Render date suitable for HTTP messages.
# "Sun, 06 Nov 1994 08:49:37 GMT"
Mojo::Date->new(784111777)->to_string;
=head2 to_words
my $str = $date->to_words;
my $str = $date->to_words(784111777);
Distance of time in words from now or a specific point in time.
# "less than a minute ago"
Mojo::Date->new(time - 1)->to_words;
# "in about a minute"
Mojo::Date->new(time + 50)->to_words;
# "5 minutes ago"
Mojo::Date->new(time - 300)->to_words;
# "about an hour ago"
Mojo::Date->new(time - 3600)->to_words;
# "in 3 hours"
Mojo::Date->new(time + 10800)->to_words;
# "a day ago"
Mojo::Date->new(time - 86400)->to_words;
# "4 days ago"
Mojo::Date->new(time - 345600)->to_words;
# "about a month ago"
Mojo::Date->new(time - 2592000)->to_words;
# "5 months ago"
Mojo::Date->new(time - 12960000)->to_words;
# "about a year ago"
Mojo::Date->new(time - 33696000)->to_words;
# "in 3 years"
Mojo::Date->new(time + 101088000)->to_words;
=head1 OPERATORS
L<Mojo::Date> overloads the following operators.
Expand Down
17 changes: 13 additions & 4 deletions lib/Mojolicious/Plugin/DefaultHelpers.pm
Expand Up @@ -3,6 +3,7 @@ use Mojo::Base 'Mojolicious::Plugin';

use Mojo::ByteStream;
use Mojo::Collection;
use Mojo::Date;
use Mojo::IOLoop;
use Mojo::Util qw(dumper sha1_sum steady_time);

Expand Down Expand Up @@ -32,10 +33,11 @@ sub register {
qw(inactivity_timeout is_fresh url_with);
$app->helper(b => sub { shift; Mojo::ByteStream->new(@_) });
$app->helper(c => sub { shift; Mojo::Collection->new(@_) });
$app->helper(config => sub { shift->app->config(@_) });
$app->helper(dumper => sub { shift; dumper(@_) });
$app->helper(include => sub { shift->render_to_string(@_) });
$app->helper(ua => sub { shift->app->ua });
$app->helper(config => sub { shift->app->config(@_) });
$app->helper(time_in_words => sub { Mojo::Date->new($_[1])->to_words });
$app->helper(dumper => sub { shift; dumper(@_) });
$app->helper(include => sub { shift->render_to_string(@_) });
$app->helper(ua => sub { shift->app->ua });
}

sub _accepts {
Expand Down Expand Up @@ -319,6 +321,13 @@ Alias for L<Mojolicious::Controller/"stash">.
%= stash('name') // 'Somebody'
=head2 time_in_words
%= time_in_words 784111777
Report the approximate distance in time from now with
L<Mojo::Date/"to_words">.
=head2 title
% title 'Welcome!';
Expand Down
38 changes: 38 additions & 0 deletions t/mojo/date.t
Expand Up @@ -68,6 +68,44 @@ is "$date", 'Sun, 06 Nov 1994 08:49:37 GMT', 'right format';
$date = Mojo::Date->new(1305280824);
is $date->to_string, 'Fri, 13 May 2011 10:00:24 GMT', 'right format';

# to_words
$date = Mojo::Date->new;
is $date->epoch(time - 1)->to_words, 'less than a minute ago', 'right words';
my $now = time;
is $date->epoch($now)->to_words($now + 1), 'less than a minute ago',
'right words';
is $date->epoch($now)->to_words($now - 1), 'in less than a minute',
'right words';
is $date->epoch($now)->to_words($now + 50), 'about a minute ago',
'right words';
is $date->epoch($now)->to_words($now - 50), 'in about a minute', 'right words';
is $date->epoch($now)->to_words($now + 300), '5 minutes ago', 'right words';
is $date->epoch($now)->to_words($now - 300), 'in 5 minutes', 'right words';
is $date->epoch($now)->to_words($now + 3600), 'about an hour ago',
'right words';
is $date->epoch($now)->to_words($now - 3600), 'in about an hour',
'right words';
is $date->epoch($now)->to_words($now + 10800), '3 hours ago', 'right words';
is $date->epoch($now)->to_words($now - 10800), 'in 3 hours', 'right words';
is $date->epoch($now)->to_words($now + 86400), 'a day ago', 'right words';
is $date->epoch($now)->to_words($now - 86400), 'in a day', 'right words';
is $date->epoch($now)->to_words($now + 345600), '4 days ago', 'right words';
is $date->epoch($now)->to_words($now - 345600), 'in 4 days', 'right words';
is $date->epoch($now)->to_words($now + 2592000), 'about a month ago',
'right words';
is $date->epoch($now)->to_words($now - 2592000), 'in about a month',
'right words';
is $date->epoch($now)->to_words($now + 12960000), '5 months ago',
'right words';
is $date->epoch($now)->to_words($now - 12960000), 'in 5 months', 'right words';
is $date->epoch($now)->to_words($now + 33696000), 'about a year ago',
'right words';
is $date->epoch($now)->to_words($now - 33696000), 'in about a year',
'right words';
is $date->epoch($now)->to_words($now + 101088000), '3 years ago',
'right words';
is $date->epoch($now)->to_words($now - 101088000), 'in 3 years', 'right words';

# Current time roundtrips
my $before = time;
ok(Mojo::Date->new(Mojo::Date->new->to_string)->epoch >= $before,
Expand Down
1 change: 1 addition & 0 deletions t/mojolicious/app.t
Expand Up @@ -65,6 +65,7 @@ is $t->app->renderer->template_handler(
is $t->app->build_controller->req->url, '', 'no URL';
is $t->app->build_controller->render_to_string('does_not_exist'), undef,
'no result';
is $t->app->time_in_words(time - 1), 'less than a minute ago', 'right result';

# Missing methods and functions (AUTOLOAD)
eval { $t->app->missing };
Expand Down

0 comments on commit 89b101f

Please sign in to comment.