You can use the sleep command, which comes preinstalled on Ubuntu, to run a command after the specified amount of time as:
sleep NUMBER[SUFFIX] && command
From man sleep:
DESCRIPTION
Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm'
for minutes, 'h' for hours or 'd' for days. Unlike most implementations
that require NUMBER be an integer, here NUMBER may be an arbitrary floating
point number. Given two or more arguments, pause for the amount of time
specified by the sum of their values.
For example, you may run:
sleep 3h 5m 25s && mpv file
to open file with the mpv media player after 3 hours, 5 minutes and 25 seconds.
sleep is perfectly usable and straightforward for running commands after a certain amount of time, however at is better for running a command at (no surprise here) a specified time.
Nevertheless, a similar behavior can be implemented with sleep. Here is an example script:
#!/bin/bash
alarm_time=$1
command=$2
convert alarm_time and current_time to seconds since 1970-01-01 00:00:00 UTC
and calculate their difference
alarm_time=$(date -d "$alarm_time" +"%s")
current_time=$(date +"%s")
diff=$(( $alarm_time - $current_time ))
convert the time difference to hours
sleep_time=$(echo "scale=5; $diff/3600" | bc)
run the command at the specified time
sleep "$sleep_time"h && $command
After saving it as alarm.sh (choose your preferred name) and making it executable, you can run it as:
/path/to/alarm.sh time command
You can add the script to your path for easier access, if you wish, and you can also hard code the command to run by replacing $2 with the command you want to run.