That is exactly what I am looking for. Thank you everyone for all your help.
I have same problem with “remove_holidays”.
I will add new binary sensor for fixing this bug.
Seems adding remove_holidays
with any valid non-holiday day causes the integration not to load and pukes an error:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 200, in _async_setup_platform
await asyncio.shield(task)
File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/src/homeassistant/homeassistant/components/workday/binary_sensor.py", line 105, in setup_platform
obj_holidays.pop(date)
File "/usr/local/lib/python3.8/site-packages/holidays/holiday_base.py", line 158, in pop
return dict.pop(self, self.__keytransform__(key))
KeyError: datetime.date(2021, 3, 18)
Testing on latest version of HA OS, i might not have enough skills to pinpoint the exact problem but seems to have issues out of the box. Haven’t filed a bug yet or searched for an existing one.
I have same problem with “remove_holidays"…
version HA: 2021.2.3
@123 that works like a charm, thanks heaps for this.
Could this also be used to compare the current date with the list of holidays and return the next holiday?
For example, if I compare today (2021-04-22) with the holidays in the script, the return value should be 2021-05-31).
I want to display the next holiday on my lovelace dashboard
Thank you
Try this:
sensor:
- platform: template
sensors:
next_holiday:
friendly_name: 'Next Holiday'
value_template: >
{% set d = now().date()|string %}
{% set holidays = ([
'2021-01-01',
'2021-05-31',
'2021-07-05',
'2021-09-06',
'2021-11-25',
'2021-12-23',
'2021-12-24'] + [d]) | sort %}
{% set i = holidays.index(d) %}
{{ holidays[i+1] if i+1 <= holidays|count-1 else 'None' }}
Thanks @123
That works brilliant!
I created a second sensor to conver the output date, that works too (I’m pretty sure it could be done in one sensor but thats fine with me now. Where I’m struggliging though was to convert the days to local language - I saw your other post here where you explain this, but the value of the above next_holiday
sensor does not have the .weekday()
or .month()
attribute, do you know how to translate the date from next_holiday to local named days and months?
- platform: template
sensors:
next_holiday_formatted:
friendly_name: "Next Holiday formatted"
value_template: >
{{ as_timestamp(states('sensor.next_holiday')) | timestamp_custom('%a, %d. %b') }}
icon_template: mdi:calendar-clock
I do but I’ll leave it for you as an exercise to expand your templating skills.
HINT:
This converts a date string into a datetime object:
{% set d = now().fromtimestamp('2021-11-25' | as_timestamp) %}
From the datetime object you can get these day, month, and weekday values (integers) which can be used as index values to respective month and weekday lists (as demonstrated in the linked example you posted).
d.day
d.month
d.weekday()
Thanks heaps @123 , your hint did the trick.
Here is the code, if somebody is looking for it. What it does, it converts the above “Next Holiday” date into a local named date .
- you need the sensor above
sensor.next_holiday
and the second sensor below (sensor.next_holiday_formatted
), format the date to your local language.
It could probably be done with one sensor only, but for me, this solution with two sensors is just fine
- platform: template
sensors:
next_holiday_formatted:
friendly_name: "Next Holiday formatted"
value_template: >
{% set months = ["Jan.", "Feb.", "März", "April", "Mai", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Dez."] %}
{% set days = ["MO", "DI", "MI", "DO", "FR", "SA", "SO"] %}
{% set d = now().fromtimestamp(states('sensor.next_holiday') | as_timestamp) %}
{{ d.timestamp() | timestamp_custom(days[d.weekday()] ~ ', %-d. ' + months[d.month-1]) }}
icon_template: mdi:calendar-clock
Good work!
Be advised that if your sensor.next_holiday
returns None
(when there is no ‘next holiday’) your template will report an error:
TypeError: an integer is required (got type NoneType)
You should check the sensor’s value first and ensure it is not None before using it.
Here’s the all-in-one version:
sensor:
- platform: template
sensors:
next_holiday:
friendly_name: 'Next Holiday'
icon_template: mdi:calendar-clock
value_template: >
{% set months = ["", "Jan.", "Feb.", "März", "April", "Mai", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Dez."] %}
{% set days = ["MO", "DI", "MI", "DO", "FR", "SA", "SO"] %}
{% set d = now().date()|string %}
{% set holidays = ([
'2021-01-01',
'2021-05-31',
'2021-07-05',
'2021-09-06',
'2021-11-25',
'2021-12-23',
'2021-12-24'] + [d]) | sort %}
{% set i = holidays.index(d) %}
{% set h = holidays[i+1] if i+1 <= holidays|count-1 else '' %}
{% if h != '' %}
{% set d = now().fromtimestamp(as_timestamp(h)) %}
{{ '{}, {}. {}'.format(days[d.weekday()], d.day, months[d.month]) }}
{% else %}
None
{% endif %}
Thanks for the advice and the all-in-one-sensor, that is much more convenient.
I’m using the same array of holidays in another sensor (binary sensor). Is it possible to save such an array in a variable so that both sensors, the sensor
and the binary sensor
can access the same values? I would then not need to paste the values into two sensors every year.
Home Assistant currently doesn’t support native global variables.
There are at least two custom components available that attempt to create the equivalent of global variables (they store the variables in the state and attributes of an entity). Feel free to explore their capabilities:
FWIW, unless you have a need for many global variables, or wish to refer to the holiday list from far more than just two entities, it’s easier to just make a copy of the list.
For now, its just the two sensors where I need to c&p the list, so thats fine. If I find myself in need of more variables down the track, I’ll give these components a go. Thank you @123 !
This is really neat. Is it possible to set the holiday date without the year. For example, New Years Day is always YYYY-01-01. How would it be possible to create the Holiday to always be on 01-01 regardless of year?
binary_sensor:
- platform: template
sensors:
holiday:
friendly_name: 'Holiday'
value_template: >
{% set holidays = [
'01-01',
'05-31',
'07-05',
'09-06',
'11-25',
'12-23',
'12-24',
'01-01'] %}
{{ now().isoweekday() in [6, 7] or (now().date()|string)[-5:] in holidays }}
Incorrect, according to the documentation:
" One other thing to watch is how the holiday
keyword is used. Your first instinct might be to add it to the exclude
configuration, thinking that it means to skip the holidays. Actually it means to exclude the days in the holidays’ list from the workdays. So when you exclude holiday
and a workday falls on that day, then that workday is excluded. Meaning the sensor will be off. If you want the workday flagged without regarding holidays, make sure that there is something in your Excludes
configuration other than holiday
."
At the time of the post, that’s how it worked. I can’t comment on how it works now as I don’t use the integration.
Same with me, I started with it, was not much satisfied, stumbled on your above post, implemented it with satisfaction.
@JDogg016 @kolia
After 2 years, it was time for me again to update those string lists in the config to have the next holidays.
I found an easy way now to eliminate this manual step also.
There is now a Holiday Sensor that you can configure, if you are lucky, your country is included too, you can also find it in HACS: GitHub - bruxy70/Holidays: 📅 Custom Home Assistant integration for public holidays - also used for garbage_collection integration to automatically move scheduled events that fall on a public holiday (by an automation blueprint)
It will create a helper, in this case “calendar.holidays”
Here is the config for the two sensors “Weekend & Holidays” and “Next Holiday with Locale Name”:
# Weekend and Holiday Sensor (will be ON on Saturday [6], Sunday [7] and all Holidays from the calendar.holidays helper
binary_sensor:
- platform: template
sensors:
weekend_holiday:
friendly_name: 'Wochenende & Feiertage'
icon_template: mdi:palm-tree
value_template: "{{ now().isoweekday() in [6, 7] or now().date()|string in state_attr('calendar.holidays', 'next_date')|string }}"
# Next Holiday with Locale Date-Name
sensor:
- platform: template
sensors:
next_holiday:
friendly_name: 'Nächster Feiertag'
icon_template: mdi:calendar-clock
value_template: >
{% set months = ["", "Jan.", "Feb.", "März", "April", "Mai", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Dez."] %}
{% set days = ["MO", "DI", "MI", "DO", "FR", "SA", "SO"] %}
{% set nh = state_attr('calendar.holidays', 'next_date') %}
{{ '{}, {}. {}'.format(days[nh.weekday()], nh.day, months[nh.month])}}
Cheers