6

I want to write a shell where given a date (day-hour-min) e.g.

10:00 AM Sun
2:30 PM Mon
...

It sleeps until that exact date & time. I thought one way of doing it is, I could get the current date and calculate the difference? then convert that into seconds and sleep for that time.

However, I am not too sure how you could do so using shell scripts?

#!/bin/bash

now=$(date '+%A %W %Y %X')
date =  2:30 PM Mon

difference = ??
sleep difference
3
  • What are you trying to do? There might be a better approach to the problem you want to solve. Commented Feb 4, 2016 at 0:31
  • 2
    The obvious answer is just to go to bed, and set an alarm. Commented Feb 4, 2016 at 1:19
  • 1
    @cat - i was thinking the same thing... now im wondering if it is the alarm.. Commented Feb 4, 2016 at 1:23

3 Answers 3

8

if the user is allowed to use at command, this is the perfect use for that:

$ at 08:00 022116
at> myscript.sh
at>      <----------- ctrl-d here
job 9 at 2016-02-21 08:00

if you get a message like "user blah is not able to run at", ask the syadmin to add this user to at.allow file or remove from at.deny file, depending on how it is used in your environment.

Unless of course you wish this days long sleep happen in the middle of your script. Even then you can cut up your script into two, writing variables you want to keep, to a file and when the time comes and second part of your script executes, it can read those variables from the stored file.

3
#!/bin/bash
NOW=$(date +"%s")
SOON=$(date +"%s" -d "3:00 PM Sun")
INTERVAL=$(($SOON-$NOW))
sleep $INTERVAL

GNU date allows you to specify the format of the output, as well as the date to display. So I use the format string "%s" to get the time in seconds since the epoch, and the same for the arbitrary time using the -d paramater. Get the difference, and you have the interval to sleep.

Checking for a date in the past is left as an exercise for the reader.

8
  • -d is a non-POSIX extension (see unix.stackexchange.com/a/1828/117549) Commented Feb 3, 2016 at 19:44
  • I have added specificity with respect to GNU date. Commented Feb 3, 2016 at 19:46
  • What's the rationale behind putting the + outside the quotes around the format string? +"$s". Commented Feb 3, 2016 at 23:17
  • @Sukminder, I habitually use uppercase mainly to distinguish from builtins and binaries, which are typically lowercase (e. g. I may assign VERB and then run $VERB as a command). I am aware that there is the potential for a conflict, but I generally check my environments for such conflicts. There is no semantic difference between upper and lower, so it's largely a matter of preference. @Digital Trauma, I place the + outside of the quoted format string to visually distinguish between the formatting itself and the invocation thereof. Commented Feb 3, 2016 at 23:37
  • @JeffSchaller, is date -v POSIX, or is that a BSD extension? Commented Feb 3, 2016 at 23:49
1

While probably you should use at as already suggested, I sometimes find the following helpful when working with time problems. I've abridged it some, but the link is there.

Seconds Since the Epoch

A value that approximates the number of seconds that have elapsed since the Epoch. A Coordinated Universal Time name (specified in terms of seconds, minutes, hours, days since January 1 of the year, and calendar year minus 1900) is related to a time represented as seconds since the Epoch, according to the expression below.

If the year is <1970 or the value is negative, the relationship is undefined. If the year is >=1970 and the value is non-negative, the value is related to a Coordinated Universal Time name according to the C-language expression, where all variables are integer types:

s +  m*60 + h*3600 + d*86400          +
(y-70)*31536000    + ((y-69)/4)*86400 -
((y-1)/100)*86400  + ((y+299)/400)*86400

Note:

The last three terms of the expression add in a day for each year that follows a leap year starting with the first leap year since the Epoch. The first term adds a day every 4 years starting in 1973, the second subtracts a day back out every 100 years starting in 2001, and the third adds a day back in every 400 years starting in 2001. The divisions in the formula are integer divisions; that is, the remainder is discarded leaving only the integer quotient.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.