Index: DEVELOP/templates/Main/view.pattern.tmpl
===================================================================
--- DEVELOP/templates/Main/view.pattern.tmpl (revision 3778)
+++ DEVELOP/templates/Main/view.pattern.tmpl (working copy)
@@ -45,7 +45,7 @@
-%TMPL:DEF{"topicaction"}%
%TMPL:END%
+%TMPL:DEF{"topicaction"}%
%TMPL:END%
Index: DEVELOP/lib/TWiki/Search.pm
===================================================================
--- DEVELOP/lib/TWiki/Search.pm (revision 3778)
+++ DEVELOP/lib/TWiki/Search.pm (working copy)
@@ -382,6 +382,7 @@
my $theTopic = $params{topic} || "";
my $theType = $params{type} || "";
my $theWebName = $params{web} || "";
+ my $theDate = $params{date} || "";
##$this->{session}->writeDebug "Search locale is $TWiki::cfg{SiteLocale}";
@@ -657,6 +658,18 @@
##$this->{session}->writeDebug "Topic list after sort = @topicList";
}
+ if( $theDate ){
+ use TWiki::Time;
+ my @ends = &TWiki::Time::parseInterval($theDate);
+ my @resultList=();
+ foreach my $topic (@topicList){
+ # if date falls out of interval: exclude topic from result
+ my $topicdate = $this->store()->getTopicLatestRevTime( $web, $topic );
+ push(@resultList, $topic) unless (($topicdate<$ends[0]) || ($topicdate>$ends[1]));
+ }
+ @topicList = @resultList;
+ }
+
# header and footer of $web
my( $beforeText, $repeatText, $afterText ) = split( /%REPEAT%/, $tmplTable );
if( $theHeader ) {
Index: DEVELOP/lib/TWiki/Time.pm
===================================================================
--- DEVELOP/lib/TWiki/Time.pm (revision 3778)
+++ DEVELOP/lib/TWiki/Time.pm (working copy)
@@ -224,4 +224,132 @@
return sprintf("%.0f", ($nextThursday - $firstFourth) / ( 7 * 86400 )) + 1;
}
+
+=pod
+
+---++ StaticMethod parseInterval( $szInterval ) -> [$iSecs, $iSecs]
+
+Convert string representing a time interval to a pair of integers
+representing the amount of seconds since epoch for the start and end
+extremes of the time interval.
+
+ * =$szInterval= - time interval string
+
+in yacc syntax, grammar and actions:
+
+interval ::= date { $$.start = fillStart($1); $$.end = fillEnd($1); }
+ | date '/' date { $$.start = fillStart($1); $$.end = fillEnd($3); }
+ | 'P' duration '/' date { $$.start = fillEnd($4)-$2; $$.end = fillEnd($4); }
+ | date '/' 'P' duration { $$.start = fillStart($1); $$.end = fillStart($1)+$4; }
+ ;
+
+an =interval= may be followed by a timezone specification string (this is not supported yet).
+
+=duration= has the form (regular expression):
+
+ P()+
+
+
+nameOfDuration may be one of:
+ * y(year), m(month), w(week), d(day), h(hour), M(minute), S(second)
+
+=date= follows ISO8601 and must include hypens. (any amount of trailing
+ elements may be omitted and will be filled in differently on the
+ differents ends of the interval as to include the longest possible
+ interval):
+
+ * 2001-01-01T00:00:00
+ * 2001-12-31T23:59:59
+
+timezone is optional and not supported yet.
+
+If the format is not recognised, will return empty interval [0,0].
+
+TODO: timezone
+ testing, especially on non valid strings
+
+=cut
+
+sub parseInterval{
+ my ($theInterval) = @_;
+
+ use HTTP::Date;
+ my @lt = localtime();
+ my $today = sprintf("%04d-%02d-%02d",$lt[5]+1900, $lt[4]+1, $lt[3]);
+ my $now = $today . sprintf("T%02d:%02d:02d",$lt[2], $lt[1], $lt[0]);
+
+ # replace $now and $today shortcuts
+ $theInterval =~ s/\$today/$today/g;
+ $theInterval =~ s/\$now/$now/g;
+
+ # if $theDate does not contain a '/': force it to do so.
+ $theInterval = $theInterval."/".$theInterval unless ($theInterval =~ /\// );
+
+ my @ends = split(/\//, $theInterval);
+
+ # first translate dates into seconds from epoch,
+ # in the second loop we will examine interval durations.
+
+ foreach my $i (0,1) {
+ # if not a period of time:
+ next if ($ends[$i] =~ "^P");
+
+ # TODO assert(must include the year)
+ if($i) {
+ # fillEnd
+ # if ending point, complete with parts from "-12-31T23:59:60"
+ # if completing ending point, check last day of month
+ # TODO: do we do leap years?
+ if (length($ends[$i]) == 7){
+ my $month = substr($ends[$i],5);
+ my @monthLens = (31,28,31,30,31,30,31,31,30,31,30,31);
+ $ends[$i] .= @monthLens[$month-1];
+ }
+ $ends[$i] .= substr("0000-12-31T23:59:59",length($ends[$i]));
+ } else {
+ # fillStart
+ # if starting point, complete with parts from "-01-01T00:00:00"
+ $ends[$i] .= substr("0000-01-01T00:00:00",length($ends[$i]));
+ }
+
+ # convert the string into integer amount of seconds
+ # from 1970-01-01T00:00:00.00 UTC
+
+ $ends[$i] = &HTTP::Date::str2time($ends[$i]);
+ }
+
+ # now we're ready to translate interval durations...
+ # ... we don't do P !!!
+
+ my @oper = ("-","+");
+ # if any extreme was a time duration, examine it
+ foreach my $i (0,1) {
+ next unless ($ends[$i] =~ /^P/);
+
+ # drop the 'P', substitute each letter with '*+',
+ # where is the amount of seconds represented by
+ # the unit. for example: w (week) becomes '*604800+'.
+ $ends[$i] =~ s/^P//;
+ $ends[$i] =~ s/y/\*31556925\+/gi; # tropical year
+ $ends[$i] =~ s/m/\*2592000\+/g; # 1m = 30 days
+ $ends[$i] =~ s/w/\*604800\+/gi; # 1w = 7 days
+ $ends[$i] =~ s/d/\*86400\+/gi;
+ $ends[$i] =~ s/h/\*3600\+/gi;
+ $ends[$i] =~ s/M/\*60\+/g; # note: m != M
+ $ends[$i] =~ s/S/\*1\+/gi;
+ # possibly append '0' and evaluate numerically the string.
+ $ends[$i] =~ s/\+$/+0/;
+ my $duration = eval($ends[$i]);
+ # the value computed, if it specifies the starting point
+ # in time, must be subtracted from the previously
+ # computed ending point. if it specifies the ending
+ # point, it must be added to the previously computed
+ # starting point.
+ $ends[$i] = eval($ends[1-$i].$oper[$i].$ends[$i]);
+ # in case the user specified both start and end as a
+ # time duration, some kind of error must be reported.
+ }
+ return @ends;
+}
+
1;
Index: DEVELOP/data/TWiki/TWikiVariablesNtoZ.txt
===================================================================
--- DEVELOP/data/TWiki/TWikiVariablesNtoZ.txt (revision 3778)
+++ DEVELOP/data/TWiki/TWikiVariablesNtoZ.txt (working copy)
@@ -1,4 +1,4 @@
-%META:TOPICINFO{author="PeterThoeny" date="1092470071" format="1.0" version="1.1"}%
+%META:TOPICINFO{author="MarioFrasca" date="1110648897" format="1.0" version="1.2"}%
%META:TOPICPARENT{name="TWikiVariables"}%
__Note:__ This topic is included by TWikiVariables
@@ -116,6 +116,7 @@
| =scope="topic"=
=scope="text"=
=scope="all"= | Search topic name (title); the text (body) of topic; or all (both) | ="text"= |
| =order="topic"=
=order="created"=
=order="modified"=
=order="editby"=
=order=
"formfield(name)"= | Sort the results of search by the topic names, topic creation time, last modified time, last editor, or named field of TWikiForms. The sorting is done web by web; in case you want to sort across webs, create a [[FormattedSearch][formatted]] table and sort it with TablePlugin's initsort | Sort by topic name |
| =limit="all"=
=limit="16"= | Limit the number of results returned. This is done after sorting if =order= is specified | All results |
+ | =date="..."= | limits the results to those pages with latest edit time in the given TimeInterval. | All results |
| =reverse="on"= | Reverse the direction of the search | Ascending search |
| =casesensitive="on"= | Case sensitive search | Ignore case |
| =nosummary="on"= | Show topic title only | Show topic summary |
Index: DEVELOP/data/TWiki/TimeInterval.txt
===================================================================
--- DEVELOP/data/TWiki/TimeInterval.txt (revision 3778)
+++ DEVELOP/data/TWiki/TimeInterval.txt (working copy)
@@ -1 +1,97 @@
-
+%META:TOPICINFO{author="MarioFrasca" date="1110650557" format="1.0" version="1.3"}%
+---++ Time Interval Strings
+
+whenever TWiki has to interpret a string as a time interval, it will apply the following rules. the result of translating a time interval string into a time interval is a pair of numbers, representing the first second in the interval and the first second following the interval, as counted from january 1st, 1970 at 0000 hours.
+
+the format we recognize is a restricted interpretation of the ISO standard 8601.
+
+
+
+---+++ the interval grammar
+
+a string is accepted as a valid time interval string if it can be described accoring to the following grammar:
+
+
+interval ::= date
+ | date '/' date
+ | 'P' duration '/' date
+ | date '/' 'P' duration
+ ;
+
+date ::= year ('-' month ('-' day ('T' hour (':' minute (':' second)))))
+ | '$today'
+ | '$now'
+ ;
+
+duration ::= NUM unit
+ | duration NUM unit
+ ;
+
+unit ::= 'y' | 'm' | 'w' | 'd' | 'h' | 'M' | 'S'
+
+year, month, day, hour, minute, second ::= NUM
+
+
+| examples | to be interpreted as |
+| ="2003"= | the whole year 2003 |
+| ="2003-03-28T/2003-05-15"= | from march 28th to may 15th of the year 2003 |
+| ="P3w/$today"= | three weeks until today |
+
+---+++ specification
+
+an interval specifying only one date is to be considered as if
+the user had written the same string as a start and end date.
+
+an incompletely specified date must be completed by including as much time as possible.
+so if a starting point is specified by the sole year, we will read 'year',
+January, the 1st, at zero hours zero minutes zero seconds.
+similarly for the ending point, December, the 31st, at 23 hours, 59 minutes and 60 seconds.
+I'm sorry for any lost leap seconds.
+
+if we were using yacc, we could think of something like this...
+
+
+interval ::= date { $$.start = fillStart($1); $$.end = fillEnd($1); }
+ | date '/' date { $$.start = fillStart($1); $$.end = fillEnd($3); }
+ | 'P' duration '/' date { $$.start = fillEnd($4)-$2; $$.end = fillEnd($4); }
+ | date '/' 'P' duration { $$.start = fillStart($1); $$.end = fillStart($1)+$4; }
+ ;
+
+
+if we accept that the format is to be quite rigid, the perl
+implementation is very easy. the rigidity lies in the fact
+that all fields have to be specified with a fixed width. this
+way it is easy completing either end with the string
+'0000-01-01T00:00:00' or '0000-12-31T23:59:60' respectively.
+
+it is not too difficult to release this rigidity, but I'm not
+familiar enough with perl to do it... all right, I'm lazy...
+
+---+++ examples
+
+| *you write* | *you mean* |
+| 2003-12-12 | on the 12th Dec 2003, from 0:00 to 23:59:59 |
+| 2003 | any second in the year 2003 |
+| 2003/P20w | the first 20 weeks of the year 2003 |
+| P20w/2003 | the last 20 weeks of the year 2003 |
+| $today | any second during the present day |
+| P2d/$today | today and yesterday |
+| P1d/$now | the last 24 hours |
+| $now/P50y | are any topics placed in the future? |
+
+---+++ possible uses
+
+one of the places where the TimeInterval can be used by the end user is in the [[TWikiVariables#VarSEARCH][%SEARCH{...}%]] variable, documented in TWikiVariables.
+
+two sample searches, from the author's personal twiki topic:
+
+|Topic modificati fra ieri ed oggi | =%SEARCH{ "." date="P2d/$today" format="[<nop>[[$web.$topic][$topic]]] <nop>" web="Main Private Ibo Servizi Culturali" scope="text" regex="on" nosearch="on" nototal="on" }%= |
+|Topic che mi riguardano modificati recentemente | =%SEARCH{ "Main\.MarioFrasca" date="P3w/$today" format="[<nop>[[$web.$topic][$topic]]] <nop>" web="Main Private Ibo Servizi Culturali" scope="text" regex="on" nosearch="on" nototal="on" }%= |
+
+
+---+++ limitations
+
+if you are entering a date at both ends of the time interval string, the end date must include all leading fields, even if these are the same as in the start date. this limitation is not really necessary and forms a proper restriction to the ISO8601 standard. look at it as "not implemented yet".
+
+| *you write* | *you mean* | *notes* |
+| 2003-12-12/14 | from 12th Dec 2003 0:00 to 14th Dec 2003 23:59:59 | not implemented (yet) |