Alarm clock

This human-friendly alarm clock uses colloquial expressions for times - "a quarter to five" rather than 4:45.

It works by subtracting the current time from the target time specified by the user and using the result as the duration for a timer. The timer must already have been created in Home Assistant.

As it stands it has limitations. You can only set the alarm for five minute intervals - "five past", "ten past" etc. - and the alarm can only be set 12 hours ahead.

To use intent scripts you have to install the intent script integration.

Custom sentence

language: "en"
intents:
  CustomAlarmclockSet:
    data:
      - sentences:
          - "wake me [up] ( at | for ) [a] {minute} {hour}"
          - "wake me [up] ( at | for ) {hour} {minute}"
          - "set ( the | an ) alarm for [a] {minute} {hour}"
          - "set ( the | an ) alarm for {hour} {minute}"          
lists:
  minute:
    values: 
      - in: "o'clock"
        out: "00"
      - in: "five past"
        out: "05"
      - in: "5 past"
        out: "05"        
      - in: "ten past"
        out: "10"
      - in: "10 past"
        out: "10"
      - in: "quarter past"
        out: "15"
      - in: "twenty past"
        out: "20"
      - in: "20 past"
        out: "20"
      - in: "twentyfive past"
        out: "25"
      - in: "25 past"
        out: "25"
      - in: "half past"
        out: "30"
      - in: "twentyfive to"
        out: "35"
      - in: "25 to"
        out: "35"
      - in: "twenty to"
        out: "40"
      - in: "20 to"
        out: "40"
      - in: "quarter to"
        out: "45"
      - in: "ten to"
        out: "50"
      - in: "10 to"
        out: "50"
      - in: "five to"
        out: "55"
      - in: "5 to"
        out: "55"
  hour:
    range:  
      from: 1
      to: 12  

Intent


CustomAlarmclockSet:
  action:
    - variables:

        hour_val: >-
          {% if minute | int(0) > 30 %}
            {{ hour | int(0) -1 }}  
          {% else %}
            {{ hour | int(0) }}
          {% endif %}

        time: >- 
          {% if now().strftime('%H') | int(0) > 12 %}
            {{ now().strftime('%H') | int(0) - 12 }}
          {% else %}
            {{ now().strftime('%H') | int(0) }}
          {% endif %}

        now_val: "{{ time | float(0) * 3600 + now().strftime('%M') | int(0) * 60 + now().strftime('%S') | int(0) }}"

        alarm_val: "{{ hour_val | int(0) * 3600 + minute | int(0) * 60 }}"

        alarm: >-
          {% if alarm_val | int(0) < now_val | int(0) %}
            {{ alarm_val | int(0) + 43200 - now_val | int(0) }}
          {% else %}
            {{ alarm_val | int(0) - now_val | int(0) }}
          {% endif %}

    - action: timer.start
      target:
        entity_id: timer.voice_alarm
      data:
        duration: "{{ alarm }}"

    - action: script.tts_response
      data:
        tts_sentence: >-
          {% if minute | int(0) == 0 %}
             {{ states('sensor.finished_phrase') }}. Alarm set for {{ hour_val }}.
          {% else %}
             {{ states('sensor.finished_phrase') }}. Alarm set for {{ hour_val }} {{ minute }}.
          {% endif %} 

Notes

In the custom sentence...

For the minute values, in: is what the voice assistant hears, out: is what it passes to the intent script. In the intent they still have to be treated as strings and converted to numbers with | int(0) or | float(0).

You need to specity "twentyfive past" and "25 past" because the voice assistant will sometimes "hear" one, sometimes the other. This may be a result of the way the voice assistant handles sentence patterns - numbers below 20 are more common and may be treated as words - but it may also depend on the user's voice, intonation, etc.

In the intent...

hour_val will be the same as hour (received from the custom sentence) for "five past five" (5.05) etc., but one less for "five to six" (5.55) etc.

time is the current hour expressed in terms of the 12-hour clock.

now_val and alarm_val - times are much easier to compare if they are converted to seconds. timer.start accepts duration in seconds.

If the alarm time alarm is less than the current time (ie the next day) add 12 hours.

sensor.finished_phrase is a random phrase to indicate completion. "OK done." etc.

Timer finished...

The alarm can sound with an automation similar to the one suggested in Timers.