Skip to content

Instantly share code, notes, and snippets.

/time.diff Secret

Created August 28, 2014 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/363bbdfbf18ee10f967f to your computer and use it in GitHub Desktop.
Save anonymous/363bbdfbf18ee10f967f to your computer and use it in GitHub Desktop.
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