mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Feb 2003
Posts: 2,812
Raccoon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
Dear Khaled,

I need a less-messy way to make a timer event fire on the hour, every hour, that also takes into account the occasional clock correction, daylight savings time changes, and traveling laptop timezone changes.

There is no cleverly simple way to achieve this that covers all of those edge cases above without writing a long winded script.

I just want the event to fire when the clock lands on the minute digits of "00", and not more than once in a ~45 minute period. Ie, doesn't rapid fire because of a time adjustment is made on the hour.

My current solution requires me to use two timers that run in tandem, the one timer updating the HH:NN value of the second timer after 45 minutes elapses, to NN:59 and then fires again after 60 seconds (which takes into account the time changing from 1 AM to 3 AM, or 2 AM to 1 AM during a time change.

Maybe you can come up with a better solution for the common simple user.

Edit:

Maybe /timer *:00 0 /commands where *:00 indicates any hour with 00 minutes, and 0 for infinite repetitions each hour. Delay is omitted to indicate that the delay will be the next wildcard time (the next hour).

Further, you could allow something like this /timer *:00,*:15,*:30,*:45 0 /commands as well.

Last edited by Raccoon; 09/11/20 02:44 AM.

Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
I'd like to see this get added natively


As for methodology, here's what I'd use:


Code
;; /onthehour name /command
alias onthehour {
  if ($isid) {
    ;; could do whatever here
    return
  }

  ;; cleanup incase the timer is being overwritten  
  if ($timer($1)) {
    .timer $+ $1 off
  }
  if (%onthehour. [ $+ [ $1 ] ]) {
    unset %onthehour. [ $+ [ $1 ] ]
  }
  
  ;; set to 59secs to reduce the chance of timer skipping *:00; def not full proof
  .timer $+ $1 -io 1 59 onthehourcheck $unsafe($1-)
}


// local: /onthehourcheck name /command
alias -l onthehourcheck {
  if ($asctime(n) || %onthehour. [ $+ [ $1 ] ]) {
    return
  }

  ;; run the command  
  ;; deviation: if the command errors, the timer is stopped unlike a typical 'forever' timer
  $2-

  ;; update state so as not to allow the timer to trigger in the next 45 minutes
  set -eu2700 %onthehour. [ $+ [ $1 ] ] $true

  ;; restart the timer
  .timer $+ $1 -io 1 59 onthehourcheck $unsafe($1-)
}


I am SReject
My Stuff
Joined: Dec 2002
Posts: 252
T
Fjord artisan
Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 252
here's a dumbed down version of what I did a while back for one of my projects where I needed a way to schedule tasks similar to the linux cron daemon. I had issues with timers and it randomly not triggering exactly on the second, It tended to vary from 00-02 at the maximum (although I do believe I rarely saw a :59 as well), so I used a multimedia timer, factoring in system ticks to derive the offset to get precisely on the second for every minute.

a cron job in linux starts with 5 tokenized positions, a command, and an optional output
[a] [b] [c] [d] [e] [command] [output]

Code
[a] - Minute 
[b] - Hour
[c] - Day
[d] - Month
[e] - Day of the Week


I wound up just tokenizing $asctime($ctime,n H d m ddd) so I could have minutes, hours (24), index of the day of the month, index of the month, and a 3 character representation of the day name, Sun,Mon,Tue.... Which gave me practically the same information to work with as a cron job, although I had to figure out evaluating rules to really mimic a cron daemon such as intervals "/" and ranges N-N, amongst other special characters like " * and , ".

If you're interested I can post the finalized project, but for sake of demonstration, this is HIGHLY stripped down just to demonstrate the execution perfectly on the minute.
Although this doesn't adjust for your situations like timezone swaps and daylight savings times, but it shouldn't be too messy to incorporate this.

To try it out, just use /crond

Code
alias crond { .timerCrond -ioh 0 1 crond.signal 1 }
alias -l crond.offset { return $calc((60 - (($ctime - $ticks / 1000) % 60) % 60) * 1000) }
alias -l crond.signal { if ($round($calc(($ticks / 1000) % 60),1) == 0) { .timerCrondSignal -h 1 $crond.offset .signal -n CRON } }
on *:SIGNAL:CRON: { echo -s Time Event: $asctime($ctime,hh:nn:ss tt) }


Result after running for some time (13 minutes):
Code
Time Event: 03:07:00 pm
Time Event: 03:08:00 pm
Time Event: 03:09:00 pm
Time Event: 03:10:00 pm
Time Event: 03:11:00 pm
Time Event: 03:12:00 pm
Time Event: 03:13:00 pm
Time Event: 03:14:00 pm
Time Event: 03:15:00 pm
Time Event: 03:16:00 pm
Time Event: 03:17:00 pm
Time Event: 03:18:00 pm
Time Event: 03:19:00 pm


Perfect execution on the minute! It may seem a bit excessive to use a multimedia timer on such a fast interval, but since it hardly does anything, it really isn't a performance hit, least none that I see on my system. Always signals exactly at a minute change, so effectively no adaptation would be needed within the code, only the signal event to handle your edge cases like moving timezones and daylight savings time adjustments. The signal event is where you'd want to code for your timed events anyways rather than setting a timer.

I use this for all sorts of nice things, like echoing day changes to all channel and query windows so I don't have that awkward instance of replying to a message at [xx:xx] coming to find out that it was a day or two ago at exactly that time, and no activity was within that window to indicate otherwise lol.

I also do it for scheduled maintenance and saving of various hash tables. There's a lot of usefulness to this and is robust much like your feature request. I hope it helps!


Link Copied to Clipboard