Displaying a card based on dates and times in an email

Hi, I am trying to create a card that pulls information about heat-health alerts that I get in emails, and displays them on my dashboard.
I would like the card to appear on my dashboard when the alert starts and disappear when it finishes.
I have managed to get the email with the imap integration, extract the alert level, and the start/end dates and times.
I’m guessing I need to somehow get the dates and times into datetime helpers, and then somehow use those as conditions for a conditional card, but I have reached the limits of my abilities.
Here is my code so far, I would be very grateful for any and all help.

template:
  - trigger:
      - platform: event
        event_type: "imap_content"
        id: "custom_event"
        event_data:
          sender: "[email protected]"
    sensor:
      - name: Health Alert Start Date
        state: >
          {{ trigger.event.data["text"] | regex_findall_index("(?:between )(\d{1,2}\/\d{1,2}\/\d{2,4})") | replace('/', '-')}}
      - name: Health Alert Start Time
        state: >
          {{ trigger.event.data["text"] | regex_findall_index("(?:between \d{1,2}\/\d{1,2}\/\d{2,4} at )(\d{1,2}:\d{1,2})") }}
      - name: Health Alert End Date
        state: >
          {{ trigger.event.data["text"] | regex_findall_index("(?:and )(\d{1,2}\/\d{1,2}\/\d{2,4})") | replace('/', '-')}}
      - name: Health Alert End Time
        state: >
          {{ trigger.event.data["text"] | regex_findall_index("(?:and \d{1,2}\/\d{1,2}\/\d{2,4} at )(\d{1,2}:\d{1,2})") }}
      - name: Health Alert Level
        state: >-
          {{ trigger.event.data["text"] | regex_findall_index("([A-Z]+)(?:\sHeat-Health Alert)") }}
  

The relevant text in the emails is:
YELLOW Heat-Health Alert - (Hot weather response) has been issued for the following regions: East Midlands, West Midlands, North East, South East, South West, Yorkshire and The Humber, East of England, London and is in effect between 23/06/2023 at 09:00 and 26/06/2023 at 09:00.

Thanks in advance guys

You can use a Markdown card to display the values of the four sensors you have created (plus whatever else you want to show). Use a Conditional card to control the Markdown card’s visi

Yes, my question is how do I get the dates and times from the email into a format where they can be used as a condition for the conditional card. As they are now, in string format, I don’t think they can be of use in that way?

What is the condition?

The condition is the dates. I want the card to show between the two dates, when the warning is active.
As I understand it, I need to get the dates into a datetime object, and then set up a binary helper that is on between those dates and off otherwise, and use that as a condition for the card. The trouble is I don’t know how to do that.

Post examples of the values of all four sensors.

If they’re in a suitable format, your template can easily combine date and time strings to form a datetime string and then convert it to a datetime object using as_datetime.

Health Alert Start Date: 23-06-2023
Health Alert End Date: 26-06-2023
Health Alert Start Time: 09:00
Health Alert End Time: 09:00

Thank you

Unfortunately, the date string is in a non-standard format (it’s backwards to the ISO standard) so as_datetime cannot convert it directly. We will need to use strptime to convert the date string.

Copy-paste the following into the Template Editor and confirm it reports either True or False. If it reports an error then it’ll need further adjustments before it can be used in a Template Binary Sensor.

{% set start = now().strptime('{} {}'.format((states('sensor.health_alert_start_date'), states('sensor.health_alert_start_time')), '%d-%m-%Y %H:%M') | as_local %}
{% set end = now().strptime('{} {}'.format((states('sensor.health_alert_end_date'), states('sensor.health_alert_end_time')), '%d-%m-%Y %H:%M') | as_local %}
{{ start < now() < end }}

Thank you very much, after some fiddling and giving up on the time, I got it to work with this:

{% set start = now().strptime(states('sensor.health_alert_start_date'), '%d-%m-%Y') | as_local %}
{% set end = now().strptime(states('sensor.health_alert_end_date'), '%d-%m-%Y') | as_local %}
{{ start < now() < end }}

I’m now setting up some automations and then I get to play with the conditional and markdown cards.
I think that was the hardest part, thank you very much for your help.

By eliminating the time portion, the template only confirms if the current day is between the start and end days (after 00:00 of the start date and before 00:00 of the end date). So if the end time is 09:00, and the current time is 08:00, the template will report false because it limits the time range to 00:00.

The example I posted takes the date and time into consideration.

Agreed, but trying your solution I got the following errors:

TemplateSyntaxError: unexpected '}', expected ')'

which I fixed by adding an extra )

and I then got:

TypeError: strptime() takes exactly 2 arguments (1 given)

which is why I went back to the start and used your example to try and write my own
Have I missed something?

The template I posted above contains a typo. There is an extraneous ( after the word format. I created the template on a mobile device and sometimes that leads to typos.

Here’s the corrected version:

{% set start = now().strptime('{} {}'.format(states('sensor.health_alert_start_date'), states('sensor.health_alert_start_time')), '%d-%m-%Y %H:%M') | as_local %}
{% set end = now().strptime('{} {}'.format(states('sensor.health_alert_end_date'), states('sensor.health_alert_end_time')), '%d-%m-%Y %H:%M') | as_local %}
{{ start < now() < end }}

ahh, i had to remove a bracket, not add one! duh, that never occurred to me!
thank you, i really should have found that.

1 Like