Displaying Date by month for a birthday list

I have a TBX with $PersonName and $DOB.

I want to be able to list the names by $DOB by month so that I can see who’s birthday is in which month.

I’m not sure how to convert the date into a month attribute that can be used. Is there is a simpler solution?

FWIW, with user attributes unless the data type is self-evident in the attribute name (e.g. ‘MyString’) it’s helpful to state the data types when asking this sort of question (please don’t take that a criticism!).

So I’ll guess $PersonName is a String and $DOB is a Date in which case take a look at aTbRef’s list of Date-time operators. For a Date-type $DOB:

$MyNumber=$DOB.month;

…which gives back a 1–12 number that represents a month Jan–Dec. If you need the month in text (String) form, you need to use .format() with a date-format string. Thus for a date whose day is in September use:

$MyString=$DOB.format("MM");

…to get a “September” value. Or, to get a “Sep” value use:

$MyString=$DOB.format("M");

The use of $MyString/$MyNumber above is simply to indicate the type of data being returned. You might want both, as this thread explores. Tinderbox can sort more easily on a number than a—to the app—arbitrary text string.

Thanks Mark, this is a great help.

I’m having a spot of bother with the date formats. I have two edicts:

$BirthMonthNumber=$DOB.format("M0");
$BirthDayNumber=$DOB.format("D");

I’m expecting them to return two digits for month and for day, but they does not do so.

Looking at Date Formats

D : formats the date of the month as a two digit number, with a leading zero as required (01-31). Example: 29
M0 : formats the month as a two digit number, with a leading zero as required: 01-12. Example: 04 . Note the second format character is zero, i.e. the format code is ‘em-zero’ not ‘em-oh’.

I’ve created a test TBX and the same issue occurs. Have I mistyped something?

date-format-test.tbx (76.8 KB)

Is $BirthMonthNumber a number?

$DOB.format("M0");

return a two-character string, such as 02. But if you assign that string to a numerical attribute, you get the number 2!

If you have a number and you want to convert it to a string, you use .format. For example

$MyNumber.format(0,2,0)

will make $MyNumber into a string that has no decimal places, is 2 characters long, and pads any unused characters to the left of the number with zeroes.

No, but you’ve overlooked data type conversion. A Number-type uses integers or decimal numbers. Left-padding with zeroes requires a string. So…

$BirthDayNumber=$DOB.format("D"); gives number 2, as the string02” returned by .format(0 is coerced from String type to Number type and in doing so the textual left-padding is lost.

Were you to use $BirthDayString=$DOB.format("D"); the result would be “02”.

As a quick test, set $StartDate for a note to a date with a single digit day then run:

$MyNumber=$StartDate.format("D");
$MyString=$StartDate.format("D");

…and you will see the first is 2 and the second “02

I’ve checked the note at Date.format(“formatString”) and it states clearly:

Returns Date as a String, formatted as per the quoted date format string formatString .

See also the article on format(data, “formatString”) the precursor to the .format() operator (same process, slightly different syntax).

I guess the wider takeaway here is if you see the wrong ‘format’ of output, you’ve likely overlooked a data-type coercion. Thus, a number-type can’t hold the value “four” (you get zero, i.e. no value) or “0004” but “000400” would result in a value of 400. Tinderbox tries to understand what you want but there are practical limitations. If you pass “000400” to a Boolean it will be true as true/false coerces to or from 0/1 and as “000400” != zero, it sets a value of true (i.e. ‘not zero’).

format() and .format() always return a string so if passing to another data type you need to consider the effects of coercion.

Thank you so much @eastgate and @mwra, this has been so helpful!

$BirthMonthNumber=$DOB.format("M0");
$BirthDayNumber=$DOB.format("D");

Were both number types so changing them to a string has solved the problem.

Here is my solution for creating a list of people’s birthdays so that the display expression tells me how old they are going to be on their next birthday. This solution also allows me to sort the birthdays in the Attribute Browser (AB) so that I can see the birthdays by month in the correct calendar order and that birthdays within any given month are sorted by the day of the month.

There are no name attributes as the name of the person in in the $Name attribute.

Sorry if this is somewhat convoluted!

My attributes are:
$DOB is a date attribute
$Age is a number attribute
$AgeThisYear is a number attribute
$BirthMonthMo is a string attribute
$BirthDayD is a string attribute
$BirthMonthMM is a string attribute
$BirthDayMonthAB is a string attribute

Edict Rules
$Age=years($DOB,date("today"));
$AgeThisYear=$Age+1;
$BirthMonthMo=$DOB.format("M0");
$BirthDayD=$DOB.format("D");
$BirthMonthMM=$DOB.format("MM");
$BirthDayMonthAB=$BirthMonthMo+" "+$BirthMonthMM;

Display Expression Rule
$Name+" Turns "+$AgeThisYear+" on "+$DOB.format("D M")

Prototype
I have one prototype to set birthdays, p_birthday.

Logic
I ended up separating all parts of the $DOB. This is because I realised that I needed them for different parts of different views that I wanted.

$AgeThisYear was needed as the $Age gives me their current age not the age they will be on their next birthday. This simply adds 1 to their $Age. This is then used in the $DisplayExpression of prototype p_birthday. It looks like this in outline view:

Attributes Explained


$DOB is the Date of birth of the person.

$Age calculates the age as a number using $Age=years($DOB,date("today")); ie “83”.

$BirthMonthMo returns the month of the DOB as a number ie “08" using, $BirthMonthMo=$DOB.format("M0”);. The “M0” is needed to give a leading zero to single digit months so that the months display in order in the AB.

$BirthMonthMM returns the month of the DOB as a string ie “August” using $BirthMonthMM=$DOB.format("MM”);. Again for us in the AB.

$BirthDayD returns the DOB day of the month as a number ie “12” using, $BirthDayD=$DOB.format(“D”);. The “D” is important as it add a leading zero to the day of month single digits. Again for use in the AB to display the day of the month in calendar order.

$BirthDayMonthAB gives me the month value as a string value in the format, “08 August" using $BirthDayMonthAB=$BirthMonthMo+" "+$BirthMonthMM;. This attribute is needed to sort the birthdays by month in calendar order.

I wanted to be able to use the AB to sort the birthdays in order of month and then by order of day. This was done with the following setup in the AB:

The query in the AB simply removes any entries that have no $DOB value by using, !$DOB=="never"

As ever, if there’s a better way of doing this please let me know.

Thanks for all you help in getting this sorted!

1 Like