Need template to calculate time between alarm and now in weekdays and weekend

If you’re going to do that, what’s the point of the day sensor? Just build it into it the next alarm timestamp/time.

    {%- macro getalarm(offsetday=0) %}
    {%- set day = (now().weekday() + offsetday) % 7 %}
    {%- set offset = offsetday * 86400 %}
    {%- set fmat = 'd' if day in range(5) else 'e' %}
    {%- set hour = 'input_number.alarmclock_w{}_hour'.format(fmat) %}
    {%- set minute = 'input_number.alarmclock_w{}_minute'.format(fmat) %}
    {%- set alarm = states(hour) | float | multiply(3600) + states(minute) | float | multiply(60) %}
    {%- set time = now().hour * 3600 + now().minute * 60 %}
    {{ (offset - time) + alarm if offsetday else alarm - time }}
    {%- endmacro %}

    {% set weekday = is_state('input_boolean.alarmclock_wd_enabled','on') %}
    {% set weekend = is_state('input_boolean.alarmclock_we_enabled','on') %}
    {% set current_day = now().weekday() %}

    {% if weekday and not weekend %}
      {% set offset = 7-current_day if current_day in range(4,7) else 1 %}
    {% elif not weekday and weekend %}
      {% if current_day in range(4) %}
        {% set offset = 5 - current_day %}
      {% else %}
        {% set offset = 6 if current_day == 6 else 1 %}
      {% endif %}
    {% elif weekday and weekend %}
       {% set offset = 1 %}
    {% else %}
       {% set offset = None %}
    {% endif %}
    
    {% if offset != None %}
      {% set today_alarm = getalarm() | float %}
      {% set next_alarm = getalarm(offset) | float %}
      {% set alarm = next_alarm if today_alarm < 0 else today_alarm %}
      {% if offset > 1 %}
        {{ alarm // 86400 }}:{{ alarm | timestamp_custom('%-H:%-M', False) }}
      {% else %}
        {{ alarm | timestamp_custom('%-H:%-M', False) }}
      {% endif %}
    {% else %}
      None 
    {% endif %}

Thanks!
Made the day sensor to see what the algorithm needed to be, and to hopefully incorporate that later on into the next alarm sensor… as you did now :wink:
Had some quirks with the adapted next alarm sensor, so changed it to hold another condition:

{% set fmat = 'd' if day in range(5) and states('input_boolean.alarmclock_wd_enabled') == 'on' 
                     else 'e' %}

without this, the sensor will still show the weekdays alarmtime, even when only weekend alarm was enabled.
of course your newest template is a huge step-up so thank you very much! Will test it immediately after my restart has finished.

side question:

why is

next_alarm_day:
        friendly_name: Next alarm day
        value_template:
          {% set day = now().weekday()|int + states('sensor.next_alarm_offset')|int  %}
      {{(day)| timestamp_custom('%A')}}

thursday and not saturday… {{day}} is 5, so I guess it makes that the 5th day of the week, but I want it to be saturday…

today (wednesday) + 3 is saturday.

I know it is the locales weekday, but can’t find the correct timestamp?

monday is 0
tuesday is 1
wednesday is 2
thursday is 3
friday is 4
saturday is 5
sunday is 6

so saturday is 5.

The reason it’s not correct in your timestamp_custom is because you don’t have a timestamp. You have an integer. Timestamps are an integer, but its based on a time in seconds from jan 1st 1970. You’re essentially asking for the day of the week that jan 1st 1970 was.

so I thought yes, and yes, I have been struggling with the addition… but even If I use |timestamp_custom(‘%A’) it remains Thursday… while it should be 5, so saturday. :confused:

Did you read my last post? It explains why it stays thursday

You’re feeding the timestamp function 5. So you are requesting the day of the week 5 seconds after midnight on january 1st 1970.

no, sure I read your post, ditched the |int and trying with as_timestamp and timestamp_custom('%a').

no result just yet though.

{% set day = as_timestamp(now().weekday())  +   as_timestamp(states('sensor.next_alarm_offset')) %}
{{as_timestamp(day)| timestamp_custom('%a') }}
{{ as_timestamp(now().replace(day=now().day+3)) | timestamp_custom('%A') }}

ok thanks,
using the offset as a variable that would make this then:

{% set offset = states('sensor.next_alarm_offset') %}
{{ as_timestamp(now().replace(day=now().day+offset|int)) | timestamp_custom('%A') }}

or

{% set offset = states('sensor.next_alarm_offset')|int %}
{{ as_timestamp(now().replace(day=now().day+offset)) | timestamp_custom('%A') }}

otherwise the addition isn’t made

Yeah, I’d do the int on the offset line, not the output line.

1 Like

cool! been a grand help, as always!

now only add a condition to not have it add the offset if alarmtime is on this day…pff seems to never be easy …

how can I add the now() time to the time next alarm, to see if they are <24:00 meaning still this day?

I have

now().time().strftime('%H:%M')
states('sensor.time_until_next_alarm')


or

I have a related sensor:

     now_master_bedroom_schedule_day:
        friendly_name: 'Now Master bedroom schedule day'
        entity_id: sensor.time
        value_template: >
          {{now().time().strftime('%H:%M') == states('sensor.master_bedroom_schedule_day')}}

which works just fine…
had a go with timestamps (setting it to the time_until_next_alarm) but it either shows nothing, or this outcome (see screenshots)

another way calculating this woud be to see if alarmtime< now ( in which case it would have to be next day…

seems to be simple but is it correct?

06
17

use that like:

      next_alarm_today:
        friendly_name: Next alarm today
        value_template: >
          {% set alarm = states('sensor.alarmclock_wd_time') if now().weekday() in range(4) 
                    else states('sensor.alarmclock_we_time') %}
          {% set now = now().time().strftime('%H:%M')%}

          {% if alarm < now %} Tomorrow
          {% elif alarm == 'Not set' %} Not set
          {% else %} Today
          {% endif %}

but I’d need it to use the time_until_next_alarm, to have it take all logic in to account of the weekdays and weekend days…

so, hopefully (need to see what will happen around the weekend) made it with another(…) sensor using the above:

      next_alarm_day:
        icon_template: >
          {% if not is_state('sensor.next_alarm_day','Not set') %} mdi:calendar-clock
          {% else %} mdi:alarm-off
          {% endif %}
        friendly_name: Next alarm day
        value_template: >
          {% set offset = states('sensor.next_alarm_offset')|int %}
          {% if not is_state('sensor.next_alarm_offset','Not set') and
                not is_state('sensor.next_alarm_today','Not set') %}
            {% if is_state('sensor.next_alarm_today','Today')%}
             {{states('sensor.next_alarm_today')}}, {{ as_timestamp(now().replace(day=now().day)) | timestamp_custom('%A')|lower }}
            {% else %}
            {{states('sensor.next_alarm_today')}}, {{ as_timestamp(now().replace(day=now().day + offset)) | timestamp_custom('%A')|lower }}
            {% endif %}
          {% elif not is_state('sensor.next_alarm_offset','Not set') %}
            {{ as_timestamp(now().replace(day=now().day  + offset)) | timestamp_custom('%A') }}
          {% else %} Not set
          {% endif %}

which give me the option to have TTS say the alarm to me :wink: as you suggested, via an extra intermediary sensor, which state is used as a variable in the speech script:

      next_alarm_text:
        friendly_name: Next alarm text
        entity_id:
          - sensor.time_until_next_alarm
          - sensor.next_alarm_day
        icon_template: >
          {% if is_state('sensor.next_alarm_text','Alarm is not set, relax') %} mdi:alarm-off
          {% else %} mdi:alarm
          {% endif %}
        value_template: >
          {% set time = states('sensor.time_until_next_alarm_full') %}
          {% set next_alarm = states('sensor.next_alarm_day')|lower %}
          {% set pickup = 'Next alarm will be ' + next_alarm + ' in ' %}
          {% if time == 'Not set, relax' %} Alarm is {{time|lower}}
          {% elif (time.split(':')|length - 1) > 1 %} 
            {{pickup}}
            {% set day = 'day' if time.split(':')[0]== '1' else 'days' %}
            {% set hour = 'hour' if time.split(':')[1]== '1' else 'hours' %}
            {% set minute = 'minute' if time.split(':')[2]== '1' else 'minutes' %}

            {% if time.split(':')[1] == '0' %} {{time.split(':')[0] }} {{day}} {{time.split(':')[2] }} {{minute}}
            {% elif time.split(':')[2] == '0' %} {{time.split(':')[0] }} {{day}} and {{time.split(':')[1] }} {{hour}} exactly
            {% else %} {{time.split(':')[0] }} {{day}}, {{ time.split(':')[1] }} {{hour}} and {{time.split(':')[2] }} {{minute}}
            {% endif%}

          {% else %}
            {{pickup}}
            {% set hour = 'hour' if time.split(':')[0]== '1' else 'hours' %}
            {% set minute = 'minute' if time.split(':')[1]== '1' else 'minutes' %}

            {% if time.split(':')[0] == '0' %} {{time.split(':')[1] }} {{minute}}
            {% elif time.split(':')[1] == '0' %} {{time.split(':')[0] }} {{hour}} exactly
            {% else %} {{time.split(':')[0] }} {{hour}} and {{time.split(':')[1] }} {{minute}}
            {% endif%}
          {% endif %}