0

so I had the idea of making a bash function that takes in a time in hh:mm:ss (24 hour format) and makes a timer till that time

kinda like a one time alarm while also showing how much time is left

I was thinking of using watch command to accomplish this

I had some questions on how to do this,

first how do I use bash to know how much is left till a certain time?

then how do I turn it into human readable format to echo to screen?

also how can I do this for times in another day in the past or future?

please help me create this function and I will post the end result here so everyone can use it.

edit: I managed to make this function from the link @terdon posted

timer () 
{ 
    start="$(date +%s -d $1)";
    while [ "$start" -ge $(date +%s) ]; do
        days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
        time="$(( $start - `date +%s` ))";
        if [ $days -gt 0 ]; then
            printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
        else
            printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
        fi;
        sleep 0.1;
    done
}

I ran into a problem, date -d $1 cannot accept a multi word argument even if all arguments are inside quotations. I use ubuntu and I am using bash, this is the code I ran to do testing. as you can see it will ignore what comes after the first word without quotations and with quotations, it gives error.

$ timer 17:25
00:04:37
$ timer sun
1 day(s) and 06:39:31
$ timer sun 17:25
1 day(s) and 06:39:20
$ timer sun 22:25
1 day(s) and 06:39:09
$ timer "sun 22:25"
date: extra operand ‘22:25’
Try 'date --help' for more information.
bash: [: : integer expression expected
4

1 Answer 1

0

It looks like you're running into an issue with passing a multi-word argument to the date command when using the -d option. To fix this, you can use the IFS (Internal Field Separator) variable to temporarily change the delimiter used by the shell when parsing arguments. Here's an example of how you can modify your function to handle multi-word arguments:

timer () 
{ 
    IFS=":" read -ra time_parts <<< "$1"
    time_str=""
    for part in "${time_parts[@]}"; do
        time_str+=" $part"
    done
    start="$(date +%s -d "$time_str")";
    while [ "$start" -ge $(date +%s) ]; do
        days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
        time="$(( $start - `date +%s` ))";
        if [ $days -gt 0 ]; then
            printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
        else
            printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
        fi;
        sleep 0.1;
    done
}

This should allow you to pass multi-word arguments to the function, such as "sun 22:25", and have them properly parsed by the date command.

Regarding the other questions you asked, you can use the command date -d to know how much time is left till a certain time and the command

date -u -d "@$time" +%H:%M:%S

to turn it into human readable format.

If you want to do this for times in another day in the past or future, you can add the date as well, like

date -u -d "2022-12-25 22:25" +%s

which will give you the timestamp of the date and time you provided.

3
  • Hi. sorry for checking your answer so late. I tried it and doing timer sun 12:00 only sees the sun and doing timer "sun 12:00" gives the error date: invalid date bash: [: : integer expression expected same for using timer 12:00 Commented Jan 20, 2023 at 16:05
  • It looks like the problem is that the time argument is missing the day name. The date command requires the day name as part of the time argument, so you will need to add it in. Try using the command timer "sun 12:00" to see if that works.
    – Mix tutor
    Commented Jan 28, 2023 at 21:16
  • still same result. Commented Feb 6, 2023 at 12:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .