API CHANGE: All timers are of the 'delayed' sort for maximum flexibility.
INTERNAL CHANGE: Don't bother with NSTimer intermediates, we abstract directly from CFRunLoopTimer
Schedule asynchronous execution of functions in the future.
-
Module
hm.timer
absoluteTime()
-><#number>
- functionlocalTime()
-><#number>
- functionnew(fn,data)
-><#timer>
- functionsleep(s)
- functiontoSeconds(timeString)
-><#number>
- function
-
Class
timer
elapsed
:<#number>
- property (read-only)nextRun
:<#number>
- propertyscheduled
:<#boolean>
- propertycancel()
- methodrun()
- methodrunAfter(predicateFn,checkInterval,continueOnError,data)
- methodrunEvery(repeatInterval,delayOrStartTime,continueOnError,data)
- methodrunIn(delay,data)
- methodrunWhen(predicateFn,checkInterval,continueOnError,data)
- methodrunWhile(predicateFn,checkInterval,continueOnError,data)
- methodsetFn(fn)
->self
- method
-
Type
intervalString
-
Type
timeOfDayString
-
Function prototypes
predicateFunction(data)
-><#boolean>
- function prototypetimerFunction(timer,data)
- function prototype
Extends
<hm#module>
Returns the number of seconds since an arbitrary point in the distant past.
- Returns
<#number>
: number of seconds, with millisecond precision or better
This function should only be used for measuring time intervals. The starting point is Jan 1 2001 00:00:00 GMT, so not the UNIX epoch.
INTERNAL CHANGE: high precision
Returns the number of seconds since midnight local time.
- Returns
<#number>
: number of seconds, with millisecond precision or better
Function hm.timer.new(fn,data)
-> <#timer>
API CHANGE: All
hs.timer
constructors are covered by the new:run...()
methods
Creates a new timer.
-
fn
:<#timerFunction>
(optional) a function to be executed later -
data
:<?>
(optional) arbitrary data that will be passed tofn
; as a convenience, you can use the special string"timer"
to havefn
receive the timer object being created -
Returns
<#timer>
: a new timer object
If fn
is not provided here, it must be set via timer:setFn()
before calling any of the :run...()
methods.
data
can be overridden (and dynamically changed) later when calling the :run...()
methods.
Halts all processing for a given interval.
s
:<#number>
interval in seconds
WARNING: this function will stop all processing by Hammermoon.
For anything other than very short intervals, use hm.timer.new()
with a callback instead.
Converts to number of seconds
-
timeString
:<#string>
a<#timeOfDayString>
or<#intervalString>
-
Returns
<#number>
: number of seconds in the interval (if<#intervalString>
) or after midnight (if<#timeOfDayString>
)
Extends
<hm#module.object>
Type for timer objects.
A timer holds an execution unit that can be scheduled for running later in time in various ways via its :run...()
methods.
After being scheduled a timer can be unscheduled (thus prevented from running) via its :cancel()
method.
API CHANGE: Was
<#hs.timer>:nextTrigger()
when negative, but only if the timer was not running.
The timer's last execution time, in seconds since.
If the timer has never been executed, this value is the time since creation.
API CHANGE:
<#hs.timer>:nextTrigger()
, with some differences.
The timer's scheduled next execution time, in seconds from now.
If this value is nil
, the timer is currently unscheduled.
You cannot set this value to a negative number; setting it to 0
triggers timer execution right away;
setting it to nil
unschedules the timer.
API CHANGE:
<#hs.timer>:running()
, with some differences.
true
if the timer is scheduled for execution.
Setting this to false
or nil
unschedules the timer.
API CHANGE: All timers can be rescheduled freely
Unschedule a timer.
The timer's <#timerFunction>
will not be executed again until you call one of its :run...()
methods.
Executes the timer now.
API CHANGE: Replaces
hs.timer.waitWhile()
andhs.timer.waitUntil()
Schedules execution of the timer after a given predicate becomes false.
predicateFn
:<#predicateFunction>
A predicate function that determines whether to contine waiting before executing the timercheckInterval
:<#intervalString>
interval between predicate checkscontinueOnError
:<#boolean>
(optional) iftrue
,predicateFn
will keep being checked even if it causes an errordata
:<?>
(optional) arbitrary data that will be passed to the<#predicateFunction>
and<#timerFunction>
The given predicateFn
will start being checked right away. As soon as it returns false
, the timer will
execute (once).
API CHANGE: This replaces all repeating timers, whether created via
hs.timer.new()
,hs.timer.doEvery()
, orhs.timer.doAt()
INTERNAL CHANGE: High frequency timers (less than 1s repeat interval) are like
hs.timer
s, i.e. the repeat schedule is managed internally by theCFRunLoopTimer
for performance. Other timers behave likehs.timer.delayed
s, i.e. they are rescheduled "manually" after every trigger.
Schedules repeated execution of the timer.
repeatInterval
:<#intervalString>
delayOrStartTime
:<?>
(optional) the timer will start executing: if omitted ornil
, right away; if an<#intervalString>
or a number (in seconds), after the given delay; if a<#timeOfDayString>
, at the earliest occurrence for the given timecontinueOnError
:<#boolean>
(optional) iftrue
, the timer will keep repeating (and executing) even if its<#timerFunction>
causes an errordata
:<?>
(optional) arbitrary data that will be passed to the<#timerFunction>
If delayOrStartTime
is a <#timeOfDayString>
, the timer will be scheduled to execute for the first time at the earliest occurrence
given the repeatInterval
, e.g.:
- If it's 17:00,
myTimer:runEvery("6h","0:00")
will set the timer 1 hour from now (at 18:00) - If it's 19:00,
myTimer:runEvery("6h","0:00")
will set the timer 5 hour from now (at 0:00 tomorrow) - If it's 21:00,
myTimer:runEvery("6h","20:00")
will set the timer 5 hours from now (at 2:00 tomorrow)
Usage:
-- run a job every day at 8, regardless of when Hammermoon was (re)started:
hm.timer.new(doThisEveryMorning,myData):runEvery("1d","8:00")
-- run a job every hour on the hour from 8:00 to 20:00:
for h=8,20 do hm.timer.new(runJob):runEvery("1d",h..":00") end
-- start doing something every second in 5 seconds:
local myTimer=hm.timer.new(mustDoThisVeryOften)
myTimer:runEvery(1,5)
-- and later (maybe in some event callback), stop:
myTimer:cancel()
API CHANGE: This replaces non-repeating timers (
hs.timer.new()
andhs.timer.doAfter()
) as well ashs.timer.delayed
s
INTERNAL CHANGE: These timers technically "repeat" into the distant future, so they can be reused at will, but are transparently added to and removed from the run loop as needed
Schedules execution of the timer after a given delay.
delay
:<#intervalString>
data
:<?>
(optional) arbitrary data that will be passed to the<#timerFunction>
Every time you call this method the "execution countdown" is restarted - i.e. any previous schedule (created
with any of the :run...()
methods) is overwritten. This can be useful
to coalesce processing of unpredictable asynchronous events into a single
callback; for example, if you have an event stream that happens in "bursts" of dozens of events at once,
use an appropriate delay
to wait for things to settle down, and then your callback will run just once.
Usage:
local coalesceTimer=hm.timer.new(doSomethingExpensiveOnlyOnce)
local function burstyEventCallback(...)
coalesceTimer:runIn(2.5) -- wait 2.5 seconds after the last event in the burst
end
API CHANGE: Not (directly) available in HS, but of dubious utility anyway.
Schedules execution of the timer every time a given predicate is true.
predicateFn
:<#predicateFunction>
A predicate function that determines whether to execute the timercheckInterval
:<#intervalString>
interval between predicate checks (and potential timer executions)continueOnError
:<#boolean>
(optional) iftrue
,predicateFn
will keep being checked even if it - or the timer's<#timerFunction>
- causes an errordata
:<?>
(optional) arbitrary data that will be passed to the<#predicateFunction>
and<#timerFunction>
The given predicateFn
will start being checked right away. Every time it returns true
, the timer will
execute.
API CHANGE: Replaces
hs.timer.doWhile()
andhs.timer.doUntil()
Schedules repeated execution of the timer while a given predicate remains true.
predicateFn
:<#predicateFunction>
A predicate function that determines whether to contine executing the timercheckInterval
:<#intervalString>
interval between predicate checks (and timer executions)continueOnError
:<#boolean>
(optional) iftrue
, the timer will keep repeating (and executing) even if its<#timerFunction>
orpredicateFn
cause an errordata
:<?>
(optional) arbitrary data that will be passed to the<#predicateFunction>
and<#timerFunction>
The given predicateFn
will start being checked right away. While it returns true
, the timer will
execute; as soon as it returns false
the timer will be canceled.
Sets the function for this timer.
-
fn
:<#function>
-
Returns
self
:<#timer>
Extends
<#string>
A string describing a time interval.
The following are valid formats: "DDdHHh"
, "HHhMMm"
, "MMmSSs"
, "DDd"
, "HHh"
, "MMm"
, "SSs"
, "NNNNms"
- they represent
an interval in days, hours, minutes, seconds and/or milliseconds.
You can also use a plain number (in seconds) wherever this type is expected.
Examples: "1m30s"
or 90
(in seconds); "1500ms"
or 1.5
.
Extends
<#string>
A string describing a time of day.
The following are valid formats: "HH:MM:SS"
, "HH:MM"
or "HHMM"
- they represent a time of day in hours, minutes, seconds (24-hour clock)
You can also use a plain number (in seconds after midnight) wherever this type is expected.
Examples: "8:00:00"
or "800"
or 28800
(in seconds).
API CHANGE: Predicate functions can receive arbitrary data.
A predicate function that controls conditional execution of a timer.
-
data
:<?>
the arbitrary data for this timer, or if"timer"
was passed tonew()
, the timer itself -
Returns
<#boolean>
: the return value will determine wheter to run, repeat, skip or cancel altogether the timer's execution, depending on what method was used
API CHANGE: Timer callbacks can receive arbitrary data.
A function that will be executed by a timer.