Birthdays next month: my list's filter uses a transcluded variable, and it's getting no items

Hello, there! I’ve been using TW for a while now, and I’m grateful for the software and the helpful community, whose messages have helped me solve problems I’ve encountered. However, I’m pretty stuck with this one, and I’d like to ask for your help.

Here is some background info:

  • A tiddler tagged Person may have a birthday field
  • The birthday field is in a timestamp format, eg. 20000101120000000
  • I’m trying to display a list of people whose birthday is this month. This is working. (Thank you to @KrisadaFantasy for your comments in this thread; this was very helpful!)
  • I also want to display a list of people whose birthday is next month. This is not working.

A. Macros & Functions

<!-- stop-gap for now; ideally would work for all months -->
\function get-next-month-string(month) [<month>compare:number:eq[12]]:then[[01]] :else[[02]]

\define get-next-month() <<get-next-month-string $(month)$>>

<!-- Expects variable: `month` -->
<!-- Finds tiddlers with the `birthday` tag, -->
<!-- whose birthday starts with any four digits, -->
<!-- then matches the value for the `month` variable -->
\define birthdays-month-filter() [has[birthday]regexp:birthday[^\d{4}$(month)$]]:sort:string[get[birthday]splitregexp[^\d{4}|\d{9}$]!is[blank]]

<!-- This works: it displays a list of the expected tiddlers -->
\define birthdays-this-month()
<$let month={{{ [<now 0MM>] }}}>
<$list filter=<<birthdays-month-filter>>>
<<birthdayForPerson>>
</$list>
</$let>
\end

<!-- This doesn't work: it displays nothing -->
\define birthdays-next-month()
<!-- Creating a variable, `month`, as the next month after the current one -->
<$let month={{{ [<now 0MM>] }}} next-month={{{ [<get-next-month>] }}} month={{{ [<next-month>] }}}>
<$list filter=<<birthdays-month-filter>>>
<<birthdayForPerson>>
</$list>
</$let>
\end

\define birthdayForPerson()
<div>
🎂 <$view field=birthday format=date template="MMM DDth" />: {{!!title}}
</div>
\end

B. Data

Assuming I have the following Person tiddlers, and that today is a date in December:

  • Alice: birthday 20201201120000000 (current month)
  • Bob: birthday 20201209120000000 (current month)
  • Charlie: birthday 20200105120000000 (next month)
  • Dee: birthday 20200124120000000 (next month)

C. Output

If this is the tiddler where I want to display the birthday info:

!! Birthdays this month

<<birthdays-this-month>>

!! Birthdays next month

<<birthdays-next-month>>

The following is displayed:

Birthdays this month

  • :birthday: 1st December: Alice
  • :birthday: 9th December: Bob

Birthdays next month

(empty – should show Charlie and Dee)

D. Questions

  • What am I doing wrong?
  • I struggled with finding a way to get the next month. I wanted to use a function, but then it got tricky passing in the parameter, because that itself would have to come from a variable, and I got snarled up in the syntax.
  • Is there a better way of organizing my macros and functions? A better way to pass the information around? A more elegant way of calculating ‘next month’ without resorting to having to counting month days and considering leap years, etc.? I’d be quite happy to write JavaScript code to accomplish this

Give this a try:

\define birthdays-month-filter()
[has[birthday]] :filter[{!!birthday}format:date[0MM]match<month>] :sort:string[{!!birthday}format:date[0DD]]
\end

\define birthdays-this-month()
<$let month={{{ [<now 0MM>] }}}>
<$list filter=<<birthdays-month-filter>>><<birthdayForPerson>></$list>
</$let>
\end

\define birthdays-next-month()
<$let month={{{ [<now MM>match[12]then[0]else<now MM>] +[add[1]pad[2]] }}}>
<$list filter=<<birthdays-month-filter>>><<birthdayForPerson>></$list>
</$let>
\end

\define birthdayForPerson()
<div>🎂 <$text text={{{ [{!!birthday}format:date[DDth MMM]] }}}/>: {{!!title}}</div>
\end

!! Birthdays this month
<<birthdays-this-month>>
!! Birthdays next month
<<birthdays-next-month>>

Notes:

  • use format:date[0MM] and format:date[0DD] to get the month and day numbers from the birthday field
  • use :filter[...] to find the tiddlers whose birthday field matches the specified <month> value
  • use :sort:string[...] to sort the tiddlers by birth date
  • within :filter[...] and :sort[...] filter runs, the currentTiddler is set to each title from the previous filter run, so you can use {!!birthday} to fetch the value of the birthday field
  • if this month is 12 use 0 then, add[1]pad[2] to get the value for the next month
  • use format:date[DDth MMM] to produce the desired output

enjoy,
-e

Thank you so much, @EricShulman!

That did exactly what I wanted it to. I like the more elegant way of calculating the next month, and the ways of filtering and formatting without needing to use regexp.

Cheers!

I’m curious though, why my original attempt didn’t work. I output the generated filter for the next month’s birthdays and it seemed to be correct, but somehow when using this filter for a $list, that didn’t work. Do you have any insight into that? This might help me understand the inner workings of TW a bit better.