Skip Menu |

This queue is for tickets about the Time-Piece CPAN distribution.

Report information
The Basics
Id: 68148
Status: new
Priority: 0/
Queue: Time-Piece

People
Owner: Nobody in particular
Requestors: mauricebuxton [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 1.16
  • 1.20
Fixed in: (no value)



Subject: Time::Piece object and undef compare as equal using <=>
When a Time::Piece object is compared to an undefined value using the <=> operator (or the other derived operators such as ==) it compares as equal. The cmp operator (and derivatives) do not have this problem, nor do comparisons to a null string or zero. Example code: use Time::Piece; $t = gmtime; print '$t <=> undef = ' . ($t <=> undef) . "\n"; print '$t cmp undef = ' . ($t cmp undef) . "\n"; print '$t <=> "" = ' . ($t <=> '') . " \n"; print '$t cmp "" = ' . ($t cmp '') . " \n"; print '$t <=> 0 = ' . ($t <=> '') . " \n"; print '$t cmp 0 = ' . ($t cmp '') . " \n"; Results: $t <=> undef = 0 $t cmp undef = 1 $t <=> "" = 1 $t cmp "" = 1 $t <=> 0 = 1 $t cmp 0 = 1 It showed up in a test along the lines of if ($t == get_a_time()) { do_something() } where 'get_a_time' returned undef to indicate that it couldn't get the time requested (a last runtime or whatever). The bug appears to be in the get_epochs function called by compare: sub get_epochs { my ($lhs, $rhs, $reverse) = @_; if (!UNIVERSAL::isa($rhs, 'Time::Piece')) { $rhs = $lhs->new($rhs); } if ($reverse) { return $rhs->epoch, $lhs->epoch; } return $lhs->epoch, $rhs->epoch; } When $rhs is not itself a Time::Piece object, 'get_epochs' tries to convert it to one using the 'new' constructor. Unfortunately, when 'new' is called on a Time::Piece object and passed undef it acts as a copy constructor. Using Time::Piece->new($rhs) instead doesn't completely solve the problem, as for an undef $rhs 'new' returns an object set to the current time -- so if $lhs is itself the current time, it still compares equal. Adding a specific test works though, something like: sub get_epochs { my ($lhs, $rhs, $reverse) = @_; return ($lhs->epoch, -1) if not defined($rhs); ... etc The problem was checked in Perl versions 5.10.1 on Ubuntu, Time::Piece versions 1.16 and 1.20, and 5.10.0 on Windows XP, Time::Piece version 1.20 (both ActiveState builds), but appears not to be OS-specific.
From: mauricebuxton [...] gmail.com
Actually, the specific test would need to take account of $reverse too! D'oh. My bad. Something like if (not defined($rhs)) { return $reverse ? (-1, 1) : (1, -1) }