(This is an expanded/corrected version of
Item2944, where the reporter improperly diagnosed the cause of the bug, which was not itself reported).
The perceived bug is that when using
$today
or
$now
in
%SEARCH%
, it is not finding topics which have just been changed. As a particular example, using an interval of '$today' will not find a topic which has just been modified. The problem is that the topic's modification time as returned by
stat()
is not within the interval returned by
TWiki::Time::parseInterval
.
Here's an analysis of the fault.
%SEARCH%
calls
$store->getTopicLatestRevTime
, which then calls
$handler->getLatestRevisionTime
, which in the case of
RcsFile
, calls
stat()
and returns the time. As was noted in the response to
Item2944, this time is in seconds since the epoch.
%SEARCH%
also calls
TWiki::Time::parseInterval
. When passed either of the strings
$today
or
$now
,
TWiki::Time::parseInterval
uses
localtime()
to obtain the elements to construct a new date string, which is passed to
TWiki::Time::parseTime
, which uses
Time::Local::timegm
to translate that into seconds since the epoch. Note that
localtime()
outputs results in the local TZ, not GMT.
However,
timegm()
is the reverse of
gmtime
and thus expects
GMT as input. This means that
parseInterval
is sending the date in the incorrect time zone to
parseTime
.
Here is code which illustrates the problem:
use Time;
my @ends = TWiki::Time::parseInterval( '$today' );
printf ("%d < %d < %d\n", $ends[0], time(), $ends[1] );
It is most easily run in the
lib/TWiki
directory as
perl -I$cwd/.. ttest.pl
When I run this code on a machine at GMT-8, I get the following results:
% date ; perl -I$cwd/.. ttest.pl
Sun Oct 29 19:30:44 PST 2006
1161993599 < 1162179046 < 1162166399
Note that the middle number (essentially "now") is greater than the last number (essentially the end of today). Not good. Now, run the program as such:
% date ; env TZ=GMT perl -I$cwd/.. ttest.pl
Sun Oct 29 19:30:46 PST 2006
1162079999 < 1162179046 < 1162252799
That's much better. At least "now" is before the end of the day.
It looks like
parseTime
is called from several places, which expect to pass it time in GMT. So,
parseInterval
should pass it GMT as well, but that means that it must convert any user provided times into GMT. (The documentation on time intervals (
TimeInterval) doesn't indicate which TZ the time should be specified in, but local TZ makes the most sense.) I've solved this problem locally by adding an optional flag parameter to
parseTime
indicating which TZ its input is in (local or GMT) and having it act accordingly. Then,
parseInterval
can continue to call it using the local TZ.
Note that this problem exists in 4.0.5
This is a PITA for anyone searching by date, and is a real bug, so upping priority to Urgent. The solution is simply to append the timezone to time strings passed to
parseTime
that don't have an exiisting timezone specification.
Actioning.
CC
The timezone parsing, and the interval parsing, was a mess. I had to do a lot of cleaning up, so i added unit tests as well as the change described above.
marking ready for release.
CC
4.1.0 released
KJL