Skip to content

Instantly share code, notes, and snippets.

Created August 28, 2014 01:51
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/4751eade988e5c6b1749 to your computer and use it in GitHub Desktop.
Save anonymous/4751eade988e5c6b1749 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..853a902 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,12 @@ 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 => sub { Mojo::Date->new($_[2])->to_words($_[1]) });
+ $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 +243,18 @@ 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
+
+ %= distance_of_time time - 90, time - 30
+
+Turn distance of time into words with L<Mojo::Date/"to_words">.
+
+=head2 distance_of_time_from_now
+
+ %= distance_of_time_from_now time - 90
+
+Turn distance of time from now into words with L<Mojo::Date/"to_words">.
+
=head2 dumper
%= dumper {some => 'data'}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment