first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / scripts / schedule / time_control.sh
1 #!/bin/sh
2 # a set of useful functions related to time.  one can get the current time as
3 # an integer, add amounts (in seconds) to the time, and set future times for
4 # activities to occur.  note that the maximum distance between now and the
5 # desired future time must be less than 24 hours away, or our system based
6 # on number of seconds will fail.
7
8 # **do not use this method directly**  you want time_as_number() instead.
9 # gets a number representing the time as hours+minutes+seconds.  the plus
10 # there indicates concatenation rather than addition.
11 function time_as_raw_number()
12 {
13   date | sed -e 's/^[^ ]*  *[^ ]*  *[0-9]*  *\([0-9][0-9]\):\([0-9][0-9]\):\([0-9][0-9]\) .*$/\1\2\3/g'
14 }
15
16 # returns a sanitized form of the time which will never inadvertently seem
17 # like an octal number to bash.  we achieve this by always putting a '1'
18 # in front of the actual time numbers.
19 function time_as_number()
20 {
21   echo 1$(time_as_raw_number)
22 }
23
24 # returns a number representing the time in X seconds from now.  this
25 # number has a '1' prefix (to ensure bash never thinks it's an octal
26 # number).
27 function add_seconds_to_now()
28 {
29   addin=$1; shift
30   time_now=$(time_as_raw_number)
31   secs=10#$(echo $time_now | sed -e 's/.*\(..\)$/\1/')
32 #echo just secs is $secs
33   mins=10#$(echo $time_now | sed -e 's/.*\(..\)..$/\1/')
34 #echo mins is $mins
35   rest=10#$(echo $time_now | sed -e 's/\(.*\)....$/\1/')
36 #echo rest is $rest
37   carry1=10#$(( (secs + addin) / 60))
38 #echo first carry is $carry1
39   secs=$(( (secs + addin) % 60))
40   if [[ secs -lt 10 ]]; then secs="0$secs"; fi
41 #echo secs now is $secs
42   carry2=10#$(( (mins + carry1) / 60))
43 #echo second carry is $carry2
44   mins=$(( (mins + carry1) % 60))
45   if [[ mins -lt 10 ]]; then mins="0$mins"; fi
46 #echo mins is now $mins
47   rest=$((rest + carry2))
48   if [[ rest -gt 23 ]]; then rest="00"; fi
49 #echo rest now is $rest
50   # emit the new value for the time after modding the values.
51   # we also add the all important preceding '1' to block octal interpretations.
52   echo 1$rest$mins$secs
53 }
54
55 # returns a successful (zero) exit value if it's really time to fire off
56 # an activity that's supposed to happen at "future_time".  the time should
57 # have been acquired from time_as_number or add_seconds_to_now.
58 future_time=
59 function compare_now_to_future()
60 {
61   curr_time=$(time_as_number)
62   if [[ curr_time -ge future_time ]]; then
63 #    echo "$curr_time: time to fire the activity!!"
64     return 0
65   else
66 #    echo "$curr_time: not time to fire yet."
67     return 1
68   fi
69 }
70
71 # resets the future test time based on the passed-in duration (in seconds).
72 function reset_future_time()
73 {
74   future_time=$(add_seconds_to_now $1)
75 }
76
77 # runs an activity of some sort if it's time to do so.
78 # this is mostly an example of using the time comparison features.
79 function run_activity_if_time()
80 {
81   # this is the length of time between the desired activities.
82   local DURATION_BETWEEN_ACTIVITIES=20
83
84   if [ -z "$future_time" ]; then
85     # we've never had a time to try the test, so we reset the future time.
86     reset_future_time $DURATION_BETWEEN_ACTIVITIES
87     return 0
88   fi
89   if compare_now_to_future; then
90     echo "$(date) Activating the activity now...."
91     # do something here.
92     reset_future_time $DURATION_BETWEEN_REBOOTS
93   fi
94 }
95
96 # set this to zero to use in normal library settings as a sourced file.
97 # set it to non-zero to turn on the debugging/unit test code.
98 time_functions_testing=0
99
100 if [ $time_functions_testing -ne 0 ]; then
101   # tests for adding seconds to current time.
102   echo time now is $(time_as_number)
103   echo time 30 seconds in future: $(add_seconds_to_now 30)
104   echo time 45 seconds in future: $(add_seconds_to_now 45)
105   echo time 60 seconds in future: $(add_seconds_to_now 60)
106   echo time 75 seconds in future: $(add_seconds_to_now 75)
107   echo time 1800 seconds in future: $(add_seconds_to_now 1800)
108
109   # test comparing to future time.
110   echo "$(date) Starting wait of 23 seconds..."
111   reset_future_time 23  # 23 seconds to wait.
112   while true; do
113     if compare_now_to_future; then
114       echo "$(date) Finished waiting 23 seconds(?)."
115       break
116     fi
117     sleep 1  # snooze a bit to avoid busy-looping.
118   done
119 fi
120
121