directus
                                
                                 directus copied to clipboard
                                
                                    directus copied to clipboard
                            
                            
                            
                        Add the ability to format $NOW dates with adjustment.
The issue
This addresses #11314
Long story short: if we want to define in no_code validation, that a date field should be greater or equal than tomorrow, it's currently impossible.
This is because the nearest option on the current API of the dynamic $NOW, is $NOW(+1 day). In turn, this will add 24H to the current time of processing, which is correct. But "tomorrow" starts at 00h00, which makes it impossible to build such validation only with no_code.
Think not only "tomorrow", but also "following month".$NOW(+1 month) will add 30days, X hours, X minutes, and so on.
"Following month" starts on the next day 1, at 00h00.
I think it's clear now, but feel free to visit the discussion mentioned above.
The solution
While the most beautiful solution would be to add an "expressive parser" that would understand things like:
- $NOW(tomorrow)
- $NOW(tomorrow at 15h00)
- $NOW(next month, on the 20th at 12h00)
... I believe we can solve this gracefully with a native solution of the library underneath, which is date-fns.
Having said so, we could leverage the native API, which exposes the format function.
With the addition of such feature, we can now achieve such validations:
// "tomorrow"
$NOW(+1 day | format: yyyy-MM-dd 00:00)
// "next month"
$NOW(+1 month | format: yyyy-MM-01 00:00) 
//"on the 15th of following month"
$NOW(+1 month | format: yyyy-MM-15 00:00) 
All we have to do is to perform an adjustment, just like before, but then "pipe" (|) to another function, format: xxxx.
The value of xxxx will be used by date-fns, so every format and specification we can use, it's documented here.
I think it will not suffice to delegate users to go there and read, hence Directus docs make brief documentation of such, with the basic examples, and then reference to the extensive, hard documentation.
My thinking process on the code implementation
First of all, disclaimer: I don't have much experience with TS 😅
So, for now, we're only adding format task to the API, which makes $NOW(+1 month | format: yyyy-MM-01 00:00) possible and working.
What I did was:
- Current adjustmentis the mainTask.
- More tasks can be added, sequentially, by piping.
This would make also possible:
$NOW(+1 month | format: yyyy-MM-01 00:00 | anotherTask: payloadForTask ) 
So, I split the whole adjustment by |, trim them, execute the first one exactly like before, and then process the rest.
Only if the task is format, then I delegate the processing to the native data-fns/format.
This is to allow possibility of the next topic.
Tests were added. They speak for themselves 😄
All signatures, types remained intact.
Considerations
As we can easily add more piped tasks, that would perform more actions on the Dateobject, I think we could also achieve to add a hook that could, of course, be customized by the default extension system!
Picture this:
$NOW( +1 day | _check: availability, rooms )
This could represent a call to the hook now:_check, providing as arguments:
- The Dateobject
- Payload: availability, rooms.
This hook now:_check must be a custom extension, so its developer is responsible to interpret payload, and return a Date object, or undefined.
This is a rough idea, but I hope the message goes through!
Breaking changes
No breaking changes. This change is purely additive.
Thank you for your time!