I am monitoring my first attempt at a plugin which uses the days operator, it’s all about reminding a user to review a tiddler if it is considered overdue a review.
So if a tiddler is set to be reviewed every 30 days then …
if 31 days have elapsed since last review it should display a red bell icon in the tiddler toolbar but if 30 days or less have elapsed it should show a green icon.
it would work just as well if the logic was…
if 30 days have elapsed since last review it should display a red bell icon in the toolbar but if 29 days or less have elapsed it should show a green icon.
So I am not overly concerned what happens on the ‘anniversary day’ as long as the decision is mutually exclusive - on that day I don’t want the logic to say that the tiddler is both overdue a review but also not overdue a review.
The days documentation is unclear on this fine point.
The examples does seem to offer non-ambiguity if they were considered function spec.
https://tiddlywiki.com/static/days%20Operator%20%28Examples%29.html
[!days:created[-800]]
→ tiddlers created more than 800 days ago
The word ‘more’ suggests that tiddlers created 800 days ago will not be included it is necessary to go to 801 days to see the change in the output - the days algorithm converts the UTC time code to days by ignoring the time part of the date.
‘more’ is obviously unambiguous with integers, 4 is more than 3, 3 is not more than 3 - we are dealing with whole days with the number of hours minutes and seconds past midnight (UTC) being ignored.
[days[-14]]
→ tiddlers modified within the last 14 days
This sounds a little more ambiguous when dealing with intervals does -3 lie within the interval [-3, 0].
I think I can see the code responsible for the current behaviour (see) $:/core/modules/filters/days.js
isWithinDays = function(dateField) {
var sign = $tw.utils.sign(targetTimeStamp - (new Date(dateField)).setHours(0,0,0,0));
return **sign === 0** || sign === dayIntervalSign;
};
The sign === 0 clause leads to the ambiguity.
The function isWithinDays is internal to the days operator and is used for both clauses, one handling the…
if(operator.prefix === "!")
case and the other handling the no-prefix case but they both use the isWithinDays function.
This means that the documented example…
[!days:created[-800]]
→ tiddlers created more than 800 days ago
Would have to be re written as follows to be accurate…
[!days:created[-800]]
→ tiddlers created 800 days ago OR more than 800 days ago
So for instance if I created a tiddler yesterday then
[!days:created[-1]]
And
[days:created[-1]]
Will both be true today but tomorrow only the first will be true and yesterday only the second was be true but for today…they are both true. For the purpose of my code the ambiguity in the result experienced on one day - ‘today’ is undesirable, it actually results in two icons appearing in the tiddler toolbar for that single day where my intention is to have only one.
This is because my code does not use conditionals, instead I have two filter expressions, they are in the same file, they appear one after the other but are independent but intended to have mutually exclusive behaviour, the desired IF … ELSE … conditional is implied by assuming this is already taken care of in the days operator.
The suggestion would be if the documented examples for days listed above are considered function spec then two functions are required…
isWithinDays() as at present
isMoreDays() to support the “prefix !” case - this function would not include the sign === 0 condition in it’s return statement.
I suggest that mutual exclusivity between the “prefix!” case and the “non-prefix!” case is important for the usefulness of the days operator - coders can compensate for “boundary conditions” when comparing days with integer intervals that represent days but mutual exclusivity between “outside” and “within” is essential - to say something is both outside and within could lead to all kinds of issues - someone writing code to decide whether to send a text message fining someone for late return of an item or alternatively to send a message telling them to renew today to avoid a fine tomorrow would probably prefer only one of these messages to be sent today