Skip Menu |

This queue is for tickets about the DateTime-Duration-Fuzzy CPAN distribution.

Report information
The Basics
Id: 68210
Status: resolved
Priority: 0/
Queue: DateTime-Duration-Fuzzy

People
Owner: Nobody in particular
Requestors: PEPL [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: 0.03



Subject: performance patch
Hi, Attached a patch for a performance improved version which also updates some of the fuzzy date logic checks
Subject: DateTime-Duration-Fuzzy-0.03-performance-and-minor-fuzzy-logic-rules-update.patch
diff -rub DateTime-Duration-Fuzzy-0.03/lib/DateTime/Duration/Fuzzy.pm DateTime-Duration-Fuzzy/lib/DateTime/Duration/Fuzzy.pm --- DateTime-Duration-Fuzzy-0.03/lib/DateTime/Duration/Fuzzy.pm 2010-12-15 16:50:32.000000000 +0100 +++ DateTime-Duration-Fuzzy/lib/DateTime/Duration/Fuzzy.pm 2011-05-15 18:16:32.000000000 +0200 @@ -3,7 +3,6 @@ use strict; use utf8; use DateTime; -use UNIVERSAL qw(isa); use Carp; use Exporter qw(import); use integer; @@ -12,59 +11,16 @@ our $VERSION = '0.03'; -sub _cmp { DateTime->compare(@_) } - -sub time_ago { - my ($time, $now) = @_; - - if (not defined $time or not isa($time, 'DateTime')) { - croak('DateTime::Duration::Fuzzy::time_ago needs a DateTime object as first parameter') - } - if (not defined $now) { - $now = DateTime->now(); - } - if (not isa($now, 'DateTime')) { - croak('Invalid second parameter provided to DateTime::Duration::Fuzzy::time_ago; it must be a DateTime object if provided') - } - - if (_cmp($time, $now) > 0) { - return 'in the future' - } - - my $treshold; - - $treshold = $now->clone->subtract(minutes => 1); - if (_cmp($time, $treshold) > 0) { - return 'just now' - } - - $treshold = $now->clone->subtract(minutes => 15); - if (_cmp($time, $treshold) > 0) { - return 'a few minutes ago' - } - - $treshold = $now->clone->subtract(minutes => 50); - if (_cmp($time, $treshold) > 0) { - return 'less than an hour ago' - } - - $treshold = $now->clone->subtract(minutes => 75); - if (_cmp($time, $treshold) > 0) { - return 'about an hour ago' - } - - $treshold = $now->clone->subtract(hours => 2); - if (_cmp($time, $treshold) > 0) { - return 'more than an hour ago' - } - - $treshold = $now->clone->subtract(hours => 6); - if (_cmp($time, $treshold) > 0) { - return 'several hours ago' - } - - $treshold = $now->clone->subtract(days => 2); - if (_cmp($time, $treshold) > 0 and $time->day == $now->day) { +my @ranges = ( + [ -1, 'in the future' ], + [ 60, 'just now' ], + [ 900, 'a few minutes ago'], # 15*60 + [ 3000, 'less than an hour ago'], # 50*60 + [ 4500, 'about an hour ago'], # 75*60 + [ 7200, 'more than an hour ago'], # 2*60*60 + [ 21600, 'several hours ago'], # 6*60*60 + [ 86400, 'today', sub { # 24*60*60 + my $time = shift; if ($time->hour < 5) { return 'tonight' } @@ -77,101 +33,61 @@ if ($time->hour < 19) { return 'this afternoon' } - # this should actually never happen return 'this evening' - } - - my $yesterday = $now->clone->subtract(days => 1); - if ($time->ymd eq $yesterday->ymd) { - return 'yesterday' - } - - $treshold = $now->clone->subtract(days => 14); - if (_cmp($time, $treshold) > 0 and $time->week_number == $now->week_number) { - return 'this week' - } - - my $last_week = $now->clone->subtract(days => 7); - $treshold = $now->clone->subtract(days => 21); - if (_cmp($time, $treshold) > 0 and $time->week_number == $last_week->week_number) { - return 'last week' - } - + }], + [ 172800, 'yesterday'], # 2*24*60*60 + [ 604800, 'this week'], # 7*24*60*60 + [ 1209600, 'last week'], # 2*7*24*60*60 + [ 2678400, 'this month', sub { # 31*24*60*60 + my $time = shift; + my $now = shift; if ($time->year == $now->year and $time->month == $now->month) { return 'this month' } - - my $last_month = $now->clone->subtract(months => 1); - $treshold = $now->clone->subtract(months => 3); - if (_cmp($time, $treshold) > 0 and $time->month == $last_month->month) { return 'last month' - } - - $treshold = $now->clone->subtract(months => 10); - if (_cmp($time, $treshold) > 0) { - return 'several months ago' - } - - $treshold = $now->clone->subtract(months => 14); - if (_cmp($time, $treshold) > 0) { - return 'about a year ago' - } - - if ($time->year == $now->year - 1) { - return 'last year' - } - - $treshold = $now->clone->subtract(years => 2); - if (_cmp($time, $treshold) > 0) { - return 'more than a year ago' - } - - $treshold = $now->clone->subtract(years => 9); - if (_cmp($time, $treshold) > 0) { - return 'several years ago' - } + }], + [ 5356800, 'last month'], # 2*31*24*60*60 + [ 24105600, 'several months ago'], # 9*31*24*60*60 + [ 31536000, 'about a year ago'], # 365*24*60*60 + [ 34214400, 'last year'], # (365+31)*24*60*60 + [ 63072000, 'more than a year ago'], # 2*365*24*60*60 + [ 283824000, 'several years ago'], # 9*365*24*60*60 + [ 315360000, 'about a decade ago'], # 10*365*24*60*60 + [ 630720000, 'last decade'], # 20*365*24*60*60 + [ 2838240000, 'several decades ago'], # 90*365*24*60*60 + [ 3153600000, 'about a century ago'], # 100*365*24*60*60 + [ 6307200000, 'last century'], # 200*365*24*60*60 + [ 6622560000, 'more than a century ago'], # 210*365*24*60*60 + [ 28382400000, 'several centuries ago'], # 900*365*24*60*60 + [ 31536000000, 'about a millenium ago'], # 1000*365*24*60*60 + [ 63072000000, 'more than a millenium ago'], # 2000*365*24*60*60 +); - $treshold = $now->clone->subtract(years => 12); - if (_cmp($time, $treshold) > 0) { - return 'about a decade ago' - } - - if ($time->year / 10 == $now->year / 10 - 1) { - return 'last decade' - } - - $treshold = $now->clone->subtract(years => 90); - if (_cmp($time, $treshold) > 0) { - return 'several decades ago' - } +sub time_ago { + my ($time, $now) = @_; - $treshold = $now->clone->subtract(years => 120); - if (_cmp($time, $treshold) > 0) { - return 'about a century ago' + if (not defined $time or not $time->isa('DateTime')) { + croak('DateTime::Duration::Fuzzy::time_ago needs a DateTime object as first parameter') } - - if ($time->year / 100 == $now->year / 100 - 1) { - return 'last century' + if (not defined $now) { + $now = DateTime->now(); } - - $treshold = $now->clone->subtract(years => 200); - if (_cmp($time, $treshold) > 0) { - return 'more than a century ago' + if (not $now->isa('DateTime')) { + croak('Invalid second parameter provided to DateTime::Duration::Fuzzy::time_ago; it must be a DateTime object if provided') } - $treshold = $now->clone->subtract(years => 900); - if (_cmp($time, $treshold) > 0) { - return 'several centuries ago' + # Use clones in UTC for safe date calculation + my $now_clone = $now->clone->set_time_zone('UTC'); + my $time_clone = $time->clone->set_time_zone('UTC'); + my $dur = $now_clone->subtract_datetime_absolute( $time_clone )->in_units('seconds'); + + foreach my $range ( @ranges ) { + if ( $dur <= $range->[0] ) { + if ( $range->[2] ) { + return $range->[2]->( $time_clone, $now_clone ); } - - $treshold = $now->clone->subtract(years => 1200); - if (_cmp($time, $treshold) > 0) { - return 'about a millenium ago' + return $range->[1]; } - - $treshold = $now->clone->subtract(years => 2000); - if (_cmp($time, $treshold) > 0) { - return 'more than a millenium ago' } return 'millenia ago' diff -rub DateTime-Duration-Fuzzy-0.03/t/01-time_ago.t DateTime-Duration-Fuzzy/t/01-time_ago.t --- DateTime-Duration-Fuzzy-0.03/t/01-time_ago.t 2010-12-15 16:50:32.000000000 +0100 +++ DateTime-Duration-Fuzzy/t/01-time_ago.t 2011-05-15 18:10:51.000000000 +0200 @@ -77,7 +77,7 @@ $then->set_month(1); t($then, $now, 'about a year ago'); -$then->set_year(2009); +$then->set_year(2009)->set_month(12); t($then, $now, 'last year'); $then->set_year(2008)->set_month(9); @@ -87,7 +87,7 @@ $then->set_year(2003); t($then, $now, 'several years ago'); -$then->set_year(1998); +$then->set_year(2000); t($then, $now, 'about a decade ago'); $then->set_year(1991); @@ -97,7 +97,7 @@ $then->set_year(1975); t($then, $now, 'several decades ago'); -$then->set_year(1901); +$then->set_year(1910); t($then, $now, 'about a century ago'); $now->set_year(2053); @@ -106,11 +106,12 @@ $then->set_year(1784); t($then, $now, 'several centuries ago'); -$then->set_year(1050); +$then->set_year(1054); t($then, $now, 'about a millenium ago'); -$now->set_year(2500); +$now->set_year(2010); +$then->set_year(1009); t($then, $now, 'more than a millenium ago'); -$then->set_year(444); +$then->set_year(1); t($then, $now, 'millenia ago');
Patch applied.