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
  • What are you trying to do? There might be a better approach to the problem you want to solve. – jpmc26 Feb 4 '16 at 0:31
  • 2
    The obvious answer is just to go to bed, and set an alarm. – cat Feb 4 '16 at 1:19
  • 1
    @cat - i was thinking the same thing... now im wondering if it is the alarm.. – mikeserv Feb 4 '16 at 1:23
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.

  • -d is a non-POSIX extension (see unix.stackexchange.com/a/1828/117549) – Jeff Schaller Feb 3 '16 at 19:44
  • I have added specificity with respect to GNU date. – DopeGhoti Feb 3 '16 at 19:46
  • What's the rationale behind putting the + outside the quotes around the format string? +"$s". – Digital Trauma Feb 3 '16 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. – DopeGhoti Feb 3 '16 at 23:37
  • @JeffSchaller, is date -v POSIX, or is that a BSD extension? – DopeGhoti Feb 3 '16 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.