-
-
Save anonymous/363bbdfbf18ee10f967f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Mojo/Date.pm b/lib/Mojo/Date.pm | |
index 5197da4..335ed22 100644 | |
--- a/lib/Mojo/Date.pm | |
+++ b/lib/Mojo/Date.pm | |
@@ -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 | |
@@ -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. | |
diff --git a/lib/Mojolicious/Plugin/DefaultHelpers.pm b/lib/Mojolicious/Plugin/D | |
index 155c574..7d1422c 100644 | |
--- a/lib/Mojolicious/Plugin/DefaultHelpers.pm | |
+++ b/lib/Mojolicious/Plugin/DefaultHelpers.pm | |
@@ -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); | |
@@ -32,8 +33,10 @@ 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(config => sub { shift->app->config(@_) }); | |
+ $app->helper( | |
+ distance_of_time_from_now => 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 }); | |
} | |
@@ -238,6 +241,12 @@ of the steps, breaking the chain. | |
my $delay = Mojo::IOLoop->delay(sub {...}, sub {...}); | |
$delay->catch(sub { $c->render_exception(pop) })->wait; | |
+=head2 distance_of_time_from_now | |
+ | |
+ %= distance_of_time_from_now 784111777 | |
+ | |
+Turn distance of time from now into words with L<Mojo::Date/"to_words">. | |
+ | |
=head2 dumper | |
%= dumper {some => 'data'} | |
diff --git a/t/mojo/date.t b/t/mojo/date.t | |
index 8a64f88..1f5963d 100644 | |
--- a/t/mojo/date.t | |
+++ b/t/mojo/date.t | |
@@ -68,6 +68,15 @@ 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'; | |
+ | |
# Current time roundtrips | |
my $before = time; | |
ok(Mojo::Date->new(Mojo::Date->new->to_string)->epoch >= $before, | |
diff --git a/t/mojolicious/app.t b/t/mojolicious/app.t | |
index e911f2b..6d25f8b 100644 | |
--- a/t/mojolicious/app.t | |
+++ b/t/mojolicious/app.t | |
@@ -65,6 +65,8 @@ 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->distance_of_time_from_now(time - 1), 'less than a minute ago', | |
+ 'right result'; | |
# Missing methods and functions (AUTOLOAD) | |
eval { $t->app->missing }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment