In Document setting , when i’m trying to set the default value of a date type attribute to today , it expands to “now” immediately , defeating my purpose. When I try to use the attribute , it doesn’t show today date.
That is actually what I would expect. The ‘now’ (same as ‘today’) designator are placeholders for the current date/time. They are not true Date data as such. What you have done above is ask Tinderbox to store the Date value for that designator. When you enter ‘now’ as a value, Tinderbox dutifully calculates the Date for that—the current date time.
You assumption, incorrect as it turns out, was that a Date attribute could store—as a default—a code expression rather than a value. A further flaw is had your idea worked the value of ‘mtgDate’† would always be today, rather than the implicit assumption that an (unknown) event would evaluate the ‘now’ to a firm data/time.
What to do? There are 2 parts here:
Setting the date, once
IOW, at the relevant event (likely, the creation of the note) you want to set:
$mtgDate = date("now");
Note that $mtgDate = "now";
is a perfectly acceptable short form of the above.
But you also only want to do that once as you want to capture that date/time and not keep resetting it. You could set the code in an OnAdd, but in any other context like a prototype, the logical OR operator is your friend:
$mtgDate |= date("now");
In this method, if the left-side attribute does not hold a local value, the right-side value is set. Otherwise the attribute is not saved.
Triggering the setting of the date
For a once-only run of the code use OnAdd or a stamp. Otherwise, consider a prototype edict. An edict as you basically want to run this once and perhaps check the value occasionally—unlike a rule which checks constantly. If using a prototype to hold the edict, set $EdictDisabled to false in the prototype before you set the code. The setting is intrinsic (and thus not inherited) and stops the edict code running in the prototype itself, unlike the notes using the prototype.
Here you’re using a simple single Date designator. But, if using a more complex data calculation e.g. the first working day of the previous week) in a number of notes, then it can make sense to do to that calculation in a discrete note or note(s) whose job it it to do that calculation and store it. Thus if you have 500 notes needing to do the calculation, the calculation is done once (per chosen periodicity) rather than 500 times. This model is something I discussed with @satikusala and which I think is in one of this demos. If so, @satikusala can you link to that demo here, please?
†. ‘mtgDate’ is a perfectly valid attribute name, but something like ‘MtgDate’ would be closer to Tinderbox attribute naming norms. Over time, I’ve found that following those cuts down on confusion/user error with long bits of code. The salient point being that the CamelCasing looks like and attribute and not like a code. Attributes use camelCase with a lowercase initial letter. The app doesn’t care, as long as what you ttpye resolves as codes. The norms address fallibility on the human code of things.
I think the answer is to calculate the date via an edict in a prototype
Mark,
I think you may have accidentally missed the OR operator from the second example of mtgDate - at least, it’s not showing at my end.
Thanks. Good spotting! Much appreciated and now fixed via post-edit to my last above.
Mark, great explanation above.
Yes, see my Tinderbox Training Video 26 - Daily Journal Time Tracking Project Management Part 1 - #26 by satikusala training, or any of my training since this one (for those interested there is a sample file with this video). You’ll find that I’m now using a “configuration” note, “TBXConfigNote,” in all my files. I use the config note to manage any calculations or lookup values that I think other notes might want to use.
This note has an Edict with the following code:
$DateToday=date("today");
$DateYesterday=date("today- 1 day"); $DateTomorrow=date("today+ 1 days");
$DateThisWeek=date("today+ 5 days");
$DateNextWeekStart=date("today+ 7 days");
$DateNextWeekEnd=date("today+ 14 days");
$DateThisMonth=date("today").month;
$DateThisYear=date("today").year;
$DisplayExpressionCache=$Name+" ("+$ChildCount+")";
In my testing, I’ve found that “today” is equivalent to “now”.
I’m pulling these values in all over the place, but the tracking agents are a good example, for instance the Events Due Today agent uses the following Query:
inside(/Tracking/By Due Date/AllEvents)&($DueDate==$DateToday("TBXConfigNote"))
This Query pulls the argument I want to use for testing the $DueDate against the time now from the config note.
- Thank you @mwra, @satikusala for teaching me different variety of ways to achieve this.
- My intention with the post was to avoid agent/edict and just have this as a default (yes I can see how easy is it to do it via above methods )
- @mwra, thanks for roping in Micheal for his demo. I was under impression mgtDate is the right naming norm for some reason. Thank you for catching this in my question.
Great, glad the helped.
This is a thorny issue as there is no right, as such. Over time, I’ve found both as a learner and a helper that the freedom that helps the real export simply confuses the less experienced. IOW, there are rules which you don’t see until you hit one but without any reason why! I hit these all the time when learning new apps.
So, Tinderbox’s rules on characters allowed in an attribute name and my ‘norms’ (both here) differ from the above reason. If you import tabular data (TSV, CSV) Tinderbox will try to honour existing heading text within the attributes it creates. If you want consistently with the norms, then it can be a good idea to ‘fix’ the headers at source or do so in an app like BBEdit before adding to Tinderbox. In context, more on tabluar import: setting up for import and Spreadsheet (Tab-Delimited Text) Import.
I struggled with this at first, since you see $MyDate, $MyInterval, $MyString, etc. in a lot of the forum demos. TBX has these pre-configured placeholder attributes for each of the data types, e.g. $MyString, $MyFiles, etc. You can use them, you can ignore them.
I find these attributes useful when I am not sure what name an attribute for a particular operation yet, or when I intended the value to be transitory, i.e. a variable for a background operation I’m trying to perform. If I want the string, date, file, etc. to be a permanent fixture in my workflow, then I create a user attribute and come up with whatever naming convension makes sense to me.
On the point of naming conversion that makes sense to me. I find that what makes sense one moment does not some days, or in some case a few minutes later, as I create the attribute. It is part of the incremental formalization process. I find that I’ll start seeing a patter of attributes that need to fall int a group, at which point I’ll go back and rename my attributes, e.g. put a group prefix in front of them, e.g. CMTrigger, CMDate…CM standing for Comms Matrix, in this example.
REMEMBER: You can easily and safely change the name and of your attributes without data loss. When you do this, however, the new attribute will be dropped to the bottom of $DisplayAttributes attribute list, so in your $DisplayExpressions you’ll want to move the attribute back to your preferred ordinal position, and you’ll need to go back through your action and export code to update the attribute name reference is your code. This feels daunting at first, but after a while you get the hang of it.
One of the great joys I derive from Tinderbox is its ability to let me set my own path, to come up with my own norms and concessions. It takes a bit of bravery and self-confidence to really embrace this, but once you do Tinderbox comes to life and turns into a true companion.
FWIW, as I’m normally documenting for others and as pertinently new to the process, I use ‘typed’ names such as MyString
or MyNumber
(incremented if needs be, e.g. MyStringB
or MyString2
) as this:
- Helps make explicit the data type returned by the right side, or the data type into which we want the right-side value to be stored by the left-side attribute.
- It makes it easier for people to copy-paste examples into test TBXs of their own to experiment.
- It is consistent with examples I use in aTbRef (certainly of late as I reviewed/revised examples recently with just this in mind).
Where someone uses user attribute names of their own in a question I try to follow that naming except where the naming goes against Tinderbox norms. In such as case I’ll likely flag the issue (and link to an explanation), and use a Tinderbox-norm-styled name for the attribute. It’s a balance between helping the questioner and using best practice for later readers.
That said, even if we say “these are just example attribute names” many peoplle are so used to apps offering them no choice they continue to use the example name … which is OK! However, for example, if you use MyString
in two different parts of your TBX to do two different tasks beware of doing a search on that attribute or using values()
as you may match notes or get values you didn’t expect.
If you’re not sure if you need to use a particular named attribute, as seen in a demo or forum ask, do ask! That, to me is just the point of user-to-user forums, to help with these little points. In most cases, likely there’s no harm and using names that make sense you you probably help in the long run. If you do rename an existing attribute, the UI and things like Displayed Attributes copy but you will need to review all your templates, stamps, actions, etc. and revise mention of the old attribute name. For templates (query: IsTemplate & $Text.contains(....
) or actions/queries ($OnAdd.contains(...
) you can query for the old values. For stamps, link type actions and export macros where access it via the Inspector you will need to review the code by eye.
In summary, attributes $MyString, etc do exist (in the System Group: Sandbox but they are also used extensively in demos and answers as a proxy date-typed generic to represent any attribute of that data type. So if the example uses MyString
and you want to use SomethningElse
(or even somethnig_else
) that should be fine as long as is a String-type attribute.
HTH
Mark, I’m no sure you can rename an existing attribute, can you? I was referring to renaming the user attributes that I create. I do it all the time as my mental constructs evolve.
A system attribute? No. An existing user attribute? Yes.