Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving the reference date parsing from a title when using tp.date.now()/moment() ? 馃 #1293

Open
I-Pch opened this issue Jan 10, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@I-Pch
Copy link

I-Pch commented Jan 10, 2024

Is your feature request related to a problem?

Well, kind of 馃槆 ... or at least, if not a problem, some type of inconsistency 馃槉 ...

When using either tp.date.now() or moment() within a Templater template, one can use a date sitting in the title of the note (i.e.: tp.file.title) as a reference date and manipulate it, in a way or another, while explicitly mentioning where needed, the MomentJS format the reference date follows so it can be used and parsed correctly by Templater when the template is applied to the note.

Example 1: A tp.date.now() template

Consider the following template applied to a note titled 2024-01-10:

<%*
let refDate = tp.date.now("YYYY-MM-DD", 0, tp.file.title, "YYYY-MM-DD");
let refDateReformatted = tp.date.now("dddd, MMMM Do YYYY", 0, tp.file.title, "YYYY-MM-DD");
let refDateYear = tp.date.now("YYYY", 0, tp.file.title, "YYYY-MM-DD");
let refDateWeekday = tp.date.now("dddd", 0, tp.file.title, "YYYY-MM-DD");
let refDateYesterday = tp.date.now("YYYY-MM-DD", -1, tp.file.title, "YYYY-MM-DD");
let refDateTomorrow = tp.date.now("YYYY-MM-DD", 1, tp.file.title, "YYYY-MM-DD");
let sameDayLastWeek = tp.date.now("dddd, MMMM Do YYYY", -7, tp.file.title, "YYYY-MM-DD");
-%>
## Results: `tp.date.now()` 
1. Reference date:
	- <% refDate %>
	- <% refDateReformatted %>
2.  Reference date year:
	- <% refDateYear %>
3. Reference date weekday:
	- <% refDateWeekday %>
4. Reference date - 1 day: 
	-  <% refDateYesterday %>
5. Reference date + 1 day:
	- <% refDateTomorrow %>
6. Same day, last week:
	- <% sameDayLastWeek %>
<% tp.file.cursor() %>

It outputs, in the note 2024-01-10:

## Results: `tp.date.now()` 
1. Reference date:
	- 2024-01-10
	- Wednesday, January 10th 2024
2.  Reference date year:
	- 2024
3. Reference date weekday:
	- Wednesday
4. Reference date - 1 day: 
	-  2024-01-09
5. Reference date + 1 day:
	- 2024-01-11
6. Same day, last week:
	- Wednesday, January 3rd 2024
Screen-recording
2024-01-10.-.tpdatenow.mov

Example 2: A moment() template

The same result can be obtained by relying directly on moment() using a template such as:

<%*
let momentRefDate = moment(tp.file.title, "YYYY-MM-DD").format("YYYY-MM-DD");
let momentRefDateReformatted = moment(tp.file.title, "YYYY-MM-DD").format("dddd, MMMM Do YYYY");
let momentRefDateYear = moment(tp.file.title, "YYYY-MM-DD").format("YYYY");
let momentRefDateWeekday = moment(tp.file.title, "YYYY-MM-DD").format("dddd");
let momentRefDateYesterday = moment(tp.file.title, "YYYY-MM-DD").subtract(1, 'd').format("YYYY-MM-DD");
let momentRefDateTomorrow = moment(tp.file.title, "YYYY-MM-DD").add(1, 'd').format("YYYY-MM-DD");
let momentSameDayLastWeek = moment(tp.file.title, "YYYY-MM-DD").subtract(1, 'w').format("dddd, MMMM Do YYYY");
-%>
## Results: `moment()` 
1. Reference date:
	- <% momentRefDate %>
	- <% momentRefDateReformatted %>
2.  Reference date year:
	- <% momentRefDateYear %>
3. Reference date weekday:
	- <% momentRefDateWeekday %>
4. Reference date - 1 day: 
	-  <% momentRefDateYesterday %>
5. Reference date + 1 day:
	- <% momentRefDateTomorrow %>
6. Same day, last week:
	- <% momentSameDayLastWeek %>
<% tp.file.cursor() %>

... which, when applied to a note titled 2024-01-10 also outputs:

## Results: `moment()` 
1. Reference date:
	- 2024-01-10
	- Wednesday, January 10th 2024
2.  Reference date year:
	- 2024
3. Reference date weekday:
	- Wednesday
4. Reference date - 1 day: 
	-  2024-01-09
5. Reference date + 1 day:
	- 2024-01-11
6. Same day, last week:
	- Wednesday, January 3rd 2024
Screen-recording
2024-01-10.-.moment.mov

So far, so good 馃槃 !
In both cases, the parsing of the date in tp.file.title works as expected, outputting correct results as I applied both templates on a note following exactly the format I said tp.file.title would be using (i.e.: YYYY-MM-DD).

This also means that:

  1. if one applies the template using tp.date.now() from above to a note which title doesn't contain any reference date to parse (e.g.: a note titled My reference date), Templater throw an alert stating:

    
     Templater Error:
     Invalid reference date format, try specifying one with the argument 'reference_format'
     
    Screen-recording
    My.reference.date.-.tpdatenow.mov
  2. if one applies the template using moment() from above to a note which title doesn't contain any reference date to parse (e.g.: a note titled My reference date once more), Templater doesn't throw an alert but Invalid date is returned instead of the expected date 馃槉.

    Screen-recording
    My.reference.date.-.moment.mov

In any cases, we're clearly being told, in a way or another, that something's wrong with the template used 馃槉 ...

Now, what I've accidentally stumbled upon recently and got me bit confused (馃槄) was:

Applying the templates from above to a note titled My reference date 1

Clearly, My reference date 1 doesn't follow the format tp.file.title is said to use in the template (YYYY-MM-DD).

And yet, what happens is that the 1 at the end of the title seems to be automatically interpreted as the year part of the date when applying either the tp.date.now() or the moment() template to My reference date 1, without failing or alerting me that something could be wrong (as Templater does if I apply the template to a note titled My reference date)...

I mean, the full date format tp.file.title should follow (YYYY-MM-DD) while being explicitly declared where needed, appears to be ignored... which, if one is not attentive enough, could lead to unexpected results 馃槆 .

E.g.: Applying the tp.date.now() template on My reference date 1

My.reference.date.1.-.tpdatenow.mov
Markdown output
## Results: `tp.date.now()` 
1. Reference date:
	- 0001-01-01
	- Monday, January 1st 0001
2.  Reference date year:
	- 0001
3. Reference date weekday:
	- Monday
4. Reference date - 1 day: 
	-  0000-12-31
5. Reference date + 1 day:
	- 0001-01-02
6. Same day, last week:
	- Monday, December 25th 0000

E.g.: Applying the moment() template on My reference date 1

My.reference.date.1.-.moment.mov
Markdown output
## Results: `moment()` 
1. Reference date:
	- 0001-01-01
	- Monday, January 1st 0001
2.  Reference date year:
	- 0001
3. Reference date weekday:
	- Monday
4. Reference date - 1 day: 
	-  0000-12-31
5. Reference date + 1 day:
	- 0001-01-02
6. Same day, last week:
	- Monday, December 25th 0000

I was running "template" tests on a note titled Untitled 24 which because of the 24 suffix, gave me, by pure luck 馃崁 , my desired results and it took me some time to realise that maybe, it shouldn't have happened this way 馃 ? ...
(Considering the 24 was there because I mindlessly created Untitled notes and didn't bother to rename them)

So, I asked in Templater channel on the Obsidian Discord Server and it turns out that at the moment, date parsing with MomentJS can be done using a strict mode or a forgiving mode, Templater currently using the latter 馃槉.

The "forgiving mode" has the advantage that when a user is trying to parse a tp.file.title date refernce in a template applied to a note titled My reference date is 2024-01-10, while setting the reference date format to YYYY-MM-DD (instead of the escaped moment format [My reference date is ]YYYY-MM-DD) it still works and produces the right results... Which is probably easier for a lot of folks out there 馃榿 !

E.g.: Applying the tp.date.now() template on My reference date is 2024-01-10

My.reference.date.is.2024-01-10.-.tpdatenow.mov
Markdown output
## Results: `tp.date.now()` 
1. Reference date:
	- 2024-01-10
	- Wednesday, January 10th 2024
2.  Reference date year:
	- 2024
3. Reference date weekday:
	- Wednesday
4. Reference date - 1 day: 
	-  2024-01-09
5. Reference date + 1 day:
	- 2024-01-11
6. Same day, last week:
	- Wednesday, January 3rd 2024

E.g.: Applying the moment() template on My reference date is 2024-01-10

My.reference.date.is.2024-01-10.-.moment.mov
Markdown output
## Results: `moment()` 
1. Reference date:
	- 2024-01-10
	- Wednesday, January 10th 2024
2.  Reference date year:
	- 2024
3. Reference date weekday:
	- Wednesday
4. Reference date - 1 day: 
	-  2024-01-09
5. Reference date + 1 day:
	- 2024-01-11
6. Same day, last week:
	- Wednesday, January 3rd 2024

On the other hand, I can't deny that I also see as potentially a bit problematic that chance (馃崁) was involved when I applied my template to the note titled Untitled 24 and it output the correct results, ignoring the fact that the reference date format used in the template and the format of the title didn't match.


Describe the solution you'd like:

As this didn't seem to be mentioned a lot (as a potential issue when it comes to date manipulations), I honestly feel like I'm nit-picking here 馃槄 ...

I mean, now that I know that a "forgiving mode" exists and is used for date parsing within Templater, I am perfectly fine with things as they currently are 馃榿.
It's probably easier for everybody and I can keep that info in mind (and in a note in Obsidian) when writing/testing my templates 馃槉.
I can absolutely live with it 馃槃 .

I think though, that maybe, something could be said about the "forgiving mode" Templater uses in the documentation.
(As it could potentially lead to undesired results in some cases)


Describe alternatives you've considered:

Well, as I asked on Discord, it appears that the options to solve this "issue" were:

  • Setting Templater to use MomentJS strict mode for dates parsing which would probably mean that some would have to update their current templates and escape what would need to be escaped (in the MomentJS fashion, using square brackets ([])).
    This would represent a breaking change which considering the lack of demand (馃檲) is clearly overkill.
  • Adding a toggle in Templater's setting to enable/disable the MomentJS strict mode dates parsing, leaving the user more in control in how they would like to see this working (and what it could require when writing a template).
    Which is an idea I like 馃槆 .
    But again, considering the lack of demand (馃檲) , that would probably add some unnecessary weight on the shoulders of the maintainers of the plugin, at the moment 馃槉 .

Additional context:

I'm filing this FR more to document all this and so others could provide some feedback/thoughts regarding the date parsing behaviour ("Forgiving mode" vs. "Strict mode") if they want to.
It's really just in case 馃槃 ... and also so the whole thing doesn't get lost on Discord 馃槉.

Speaking of Discord, I'm leaving here the links to the various messages from the conversation I had with Zachatoo about this:

I am also profoundly sorry for the wall of text this FR turned out to be as I tried to be as precise as I could 馃槆 !
And I can't thank Zachatoo enough for taking the time to look at this 馃檶 !

@I-Pch I-Pch added the enhancement New feature or request label Jan 10, 2024
@IchHabRecht
Copy link

Hi @I-Pch, hi @Zachatoo,

Thank you very much for this detailed issue description. I can here for a likely related problem. I want to check if the filename is already in a "YYYY-MM-DD" format. If it is, nothing should be changed but if not I want to trigger a selection promt to choose from a couple of options. I'm now using a try/catch statement together with tp.date.now (which throws an error if parsing with the given format fails). Unfortunately there isn't any error for a filename with a number in it and I need to check the year (I added a check if the year is below 2000 it's an invalid date). I tried to use moment with strict mode but as mentioned in the discord conversation templater checks the date itself and shows an error message (and stops the script processing).

Is there any workaround I could use to check the file title according a given date format? I think I will use a regular expression check by now to handle my use case.

@Zachatoo
Copy link
Collaborator

@IchHabRecht You can use moment directly like this:

<%*
if (!moment(tp.file.title, "YYYY-MM-DD", true).isValid()) {
  // do something if filename isn't in YYYY-MM-DD format
}
-%>

@IchHabRecht
Copy link

Hi @Zachatoo

Thanks for answering so quickly. Unfortunate it seems I don't get a moment object for invalid titles in strict mode. Templater seems to catch that case internally. An error message is shown and the script seems to be stopped.

@Zachatoo
Copy link
Collaborator

Zachatoo commented Jan 18, 2024

@IchHabRecht What's your full template? Or a minimum reproducible example? The example I provided seems to be working for me.

2024-01-17_18-52-25.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants