Filter errors when executed, but 'LIST MATCHES' and 'DEBUG' work as expected

Discussions related to the 1.36.x series of ZoneMinder
Post Reply
_LD
Posts: 6
Joined: Mon Jun 20, 2022 11:02 pm

Filter errors when executed, but 'LIST MATCHES' and 'DEBUG' work as expected

Post by _LD »

I'm setting up some annual archive filters. The filters work when selecting 'LIST MATCHES' on the filter page (with the 'System Load' line removed, obviously, to avoid that SQL error), and the 'DEBUG' modal also shows the expected dates; however, executing the filters results in date errors, and the filters subsequently being skipped.

One of the filters:

Code: Select all

		System Load	less than			7
and	(	Storage Area	equal to			Cam_Garage
or		Storage Area	equal to			Archives-Cam_Garage			)
and	(	Start Date	greater than or equal to	first day of January last year
and 		Start Date	less than or equal to		last day of December last year		)
'DEBUG' modal shows:

Code: Select all

SQL SELECT E.*,M.Name AS MonitorName,M.DefaultScale
FROM Monitors AS M INNER JOIN Events AS E ON (M.Id = E.MonitorId)
WHERE
E.SystemLoad < '7' and ( E.StorageId = '1' or E.StorageId = '5' ) and ( to_days(E.StartDateTime) >= to_days('2023-01-01 00:00:00') and to_days(E.StartDateTime) <= to_days('2023-12-31 00:00:00') ) ORDER BY Id ASC LIMIT 5
Errors in web log:

Code: Select all

zmfilter_21	5444	ERR	Unable to parse date string 'first day of January last year'					zmfilter.pl	-
zmfilter_21	5444	ERR	Error parsing date/time 'first day of January last year', skipping filter 'DeepStorage-Garage'	zmfilter.pl	-
zmfilter_21	5444	ERR	Error parsing Sql. skipping filter 'DeepStorage-Garage'						zmfilter.pl	-

Suggestions for an alternative filter setup that works, and doesn't require hard-coded dates?
User avatar
iconnor
Posts: 3280
Joined: Fri Oct 29, 2010 1:43 am
Location: Toronto
Contact:

Re: Filter errors when executed, but 'LIST MATCHES' and 'DEBUG' work as expected

Post by iconnor »

List matches and debug use php date parsing libraries. The executed filter uses perl, and apparently does not support things like "first day of january of last year"

I am amazed that the php libs do, that's cool...

We really only support constructs like -1 year. -1 month, -7 days etc.
_LD
Posts: 6
Joined: Mon Jun 20, 2022 11:02 pm

Re: Filter errors when executed, but 'LIST MATCHES' and 'DEBUG' work as expected

Post by _LD »

Ah, thank you much for the info, iconnor. (And, of course, now that you've clarified that, I see the wiki also mentions the automated filters use perl instead of PHP...)

I tried every combination I could think of, but I couldn't get the Date::Manip module in perl to calculate the year in combination with any other calculation (i.e. it can calculate day and/or month with the current or hard-coded year, or calculate the year with today's day and month, but can't calculate all three at once).

At the moment, I've implemented a janky edit to /usr/share/perl5/ZoneMinder/Filter.pm on my installation that utilizes the PHP strtotime function, since it's more capable (and functions consistently with the "LIST MATCHES" and "DEBUG" buttons on the filter page); this is, however, hardly more convenient to maintain then simply hard-coding the year in my annual archive filters at the beginning of each year, so I think this was little more than an exercise in curiosity.

To anyone else that may be interested in utilizing the more-flexible features of PHP's strtotime, even temporarily, all I did was replace this function:

Code: Select all

#
# More or less replicates the equivalent PHP function
#
sub strtotime {
  my $dt_str = shift;
  return Date::Manip::UnixDate($dt_str, '%s');
}
With the following:

Code: Select all

#
# Call the equivalent PHP function; fallback to perl function
#
sub strtotime {
  my $dt_str = shift;
  my $dt_val = strtotime_php($dt_str);
  if ( !$dt_val ) {
    # default to original perl if PHP returns a bad date
    $dt_val = strtotime_perl($dt_str);
  }
  return $dt_val;
}

#
# Calls the equivalent PHP function
#
sub strtotime_php {
  my $dt_str = shift;
  return readpipe( "php -r ' echo strtotime( \"$dt_str\" ); '" );
}

#
# More or less replicates the equivalent PHP function
#
sub strtotime_perl {
  my $dt_str = shift;
  return Date::Manip::UnixDate($dt_str, '%s');
}

EDIT:
Incidentally, the Events pages and Filtering pages seem noticeably faster with the PHP strtotime function, which was entirely unexpected.

EDIT 2:
Nope, the speedup on the Events pages and Filtering pages appears to have resulted from some ZoneMinder update between 1.36.20 and 1.36.33 (I just updated a couple days prior). Nice job!
Post Reply