How to check if date is tomorrow

I’ve got 3 date inputs in Hass that are used for 3 waste bins when they’re emptied. They’re updated a REST API that I fetch in Node RED. What I would like to have is a notification that waste bin X or Y are due for tomorrow. I want to send the notification at a specific time, so an automation should run daily at that time.

So my question is, how do I check if the date input is next day? I found some pieces of code, but they’re very unclear and don’t seem easy to use. I rather do as much as possible via the UI.

Otherwise it would be a lot faster and easier to just do that in Node RED as well.

1 Like

If you’re already deep in Node-RED, and all you want is a notification (which is just a simple service call), just do it in Node-RED.

The alternative is a template trigger that looks at the input_datetime, converts it to a timestamp and then sees if that timestamp is less than the current time sensor as a timestamp plus 24 hours. It’s a pretty ugly looking template when you could, instead, just do it in Node-RED.

Cheers that’s what I was afraid of! I’ll go play in Node RED then. :+1:

The template is actually pretty simple. I created the following and tested it in the developer template tool. The template code is for a binary_sensor that will turn on when you are within a day:

    test_date_next_day:
      friendly_name: "Turn ON if the desired date is less than one day from now" 
      value_template: >
        {% set next_date = state_attr('input_datetime.test_input_datetime','timestamp') %}
        {% set current_timestamp = now().timestamp() %}
        {% set delta = (next_date - current_timestamp)/86400 %}
        {{ delta <= 1.0 and delta >= -1.0 }}

The variable next_date comes from your input_datetime. To be complete, timestamp is in seconds, so dividing the delta between now and the next date by 86400 just puts it into days. If you ran an automation that triggered whenever this turns on, you’d have your indicator.

I’m your input_datetime is a date only (doesn’t include time). At midnight on that day, the delta would be 0.0 (now() and next_date would be exactly the same). A second later it would be negative because now() becomes greater than next_date and the binary sensor would turn off. That’s why the second condition in the logic statement is a -1.0. If you want it to turn off for the day-of, then the logic would change to:

        {{ delta <= 1.0 and delta >= 0.0 }}
1 Like

simple? yes. ugly (in my opinion)? also yes.

However, if doing it in a Home Assistant template is desired, I don’t think it gets much prettier than what you’ve done. So Kudos.

It’s not much prettier in my automation tool of choice, pyscript (though, at least this bit of code handles the template binary_sensor, the automation, the notification, everything)

from datetime import datetime, timedelta


@state_trigger('input_datetime.test_input_datetime')
@task_unique('day_before_notify')
def day_before_notify():
    notify_at = datetime.fromtimestamp(input_datetime.test_input_datetime.timestamp) + timedelta(days=1)

    task.wait_until(time_trigger=f'once("{notify_at}")')
    notify.me(message="take the bin out")

If the input_datetime only shows date (like 2020-12-25) and not date and time, then this simple template gets the job done:

   {{ (now().date() + timedelta(days=1)) | string == states('input_datetime.garbage_day') }}

To experiment with it, paste this into the Template Editor:

Today is: {{ now().date() }}
Garbage Day is: {{ states('input_datetime.garbage_day') }}

 
Is tomorrow garbage day?  {{ (now().date() + timedelta(days=1)) | string == 
                             states('input_datetime.garbage_day') }}

Here are the results on my system;

Screenshot from 2020-12-23 18-47-24

2 Likes

This is basically what I do, by formatting the timestamps as yyyy-mm-dd and comparing them. It’s pretty simple.

There’s no formatting of timestamps in the template I posted. In fact, it’s not using any timestamps. It’s using DateTime objects and then performing a string comparison.

Yes - yours is neater, I do it a different way because of the limitations of my input data. :slightly_smiling_face: I just wanted to point out that your solution can also be used when input is a timestamp rather than a datestamp.

Can you provide a template that demonstrates what you mean?

Sure. This is the code that I’m using, I’m sure it could be shortened/neatened by someone with more experience working with time manipulation.

{{ (as_timestamp(now())+86400)|timestamp_custom("%F") == as_timestamp(state_attr("sensor.bin_scraper_v2", "nextdate"))|timestamp_custom("%F") }}

(now())+86400) is (I think) a datetime object corresponding to 24 hours from now

state_attr(“sensor.bin_scraper_v2”, “nextdate”) is the string 2020-12-28 00:00:00

as_timestamp converts them both to timestamps, and then timestamp_custom("%F") converts them to a string in YYYY-MM-DD format, so this template currently evaluates whether “2020-12-25” == “2020-12-28” and returns false.

As I said before, I’m sure this isn’t the most efficient way of doing this - I’m very new to working with time.

I find this thread hugely helpful when working with time in templates: The EPIC Time Conversion and Manipulation Thread!

I think I’d stick with a simple text comparison, it shorter, neater, more readable and does exactly what it says on the tin.

Previously, you said that my solution could be used when the input is a timestamp:

Here’s is the example you provided:

{{ (as_timestamp(now())+86400)|timestamp_custom("%F") == 
    as_timestamp(state_attr("sensor.bin_scraper_v2", "nextdate"))|timestamp_custom("%F") }}

Can you explain how it is an example of "your solution can also be used when input is a timestamp*?

I see nothing in it that resembles the technique I used:

{{ (now().date() + timedelta(days=1)) | string ==
    states('input_datetime.garbage_day') }}

The really cool thing about this thread is that there are multiple ways to do this! I really appreciated reading through the various solutions (and that’s why I enjoy working with HA). I really like the solution @123 poses (clean and simple and maybe saves a clock cycle or two over mine). I’m not sure how that would work with a date-and-time input_datetime, though. The equality check would only be True when the date AND time are exactly the same. So it would only be True for one second.

It would work with timestamps from a date-only input_datetime as they would evaluate to the timestamp at midnight for each one. This would give the same result as @123 provided.

It doesn’t and that’s why the first line of my post includes a qualification:

If the input_datetime only shows date (like 2020-12-25 ) and not date and time

However, Gerben321’s goal is to “check if the date input is next day” so the assumption is that trash day is just a date and not a date and time. Anyway, apparently Gerben321 left the discussion a long time ago (and is using Node-Red).

1 Like

If you have date and time rather than date only, just truncate the date time to provide the date.
It’s a matter of a pipe, two square brackets with a colon and a start and stop character. So ignoring spaces - 7 characters. And saves so much faff.

If you have an input_datetime that shows time only, and you want to know when it is 5 hours prior to that time, here’s how to compute it:

{{ ((now() + timedelta(hours=5)).time() | string) [:5] == 
   states('input_datetime.time_only') }}

If you have an input_datetime that shows date and time, and you want to know when it is 5 hours prior to that date and time, here’s how to compute it:

{{ ((now() + timedelta(hours=5)) | string) [:16] == 
   states('input_datetime.date_and_time') [:16] }}

The reason it uses [:16] is because it slices off the seconds from the datetime string (in other words, the resolution is to the minute and not to the second).

For completeness, here’s the version for an input_datetime containing the date only and you want to know when it’s 1 day prior to that date:

   {{ (now().date() + timedelta(days=1)) | string == 
      states('input_datetime.date_only') }}

Thanks all for the discussion (feel free to continue). I have indeed used Node RED for it. I think it’s way more sexy looking and easier to understand. But I might have another look at it some time. My input is date only (not time).

Beauty is in the eye of the beholder. Post it so we can all judge its relative sex appeal.

1 Like

Yeah, I definitely agree.

I tried Nodered a couple of times and found that even though it’s “graphical” and you can more easily see the flows/connections between the nodes setting up the node info themselves was still way too fiddly. I found it way more complicated than just typing it all out in yaml.

Maybe I used some bad examples in my tests tho. :man_shrugging:

2 Likes