This example code in this article demonstrates how to use a persistent counter to simulate a count of milliseconds.
The Lua time function os.time()
only returns a time value to the nearest second. There are many occasions where milliseconds would be useful to distinguish between timed events. The code in this article solves this problem by simulating milliseconds, and concatenating them to the current time.
Warning! If real timed milliseconds required then please see suggestion at the bottom of this page.The “millisecond values” in example on this page are not timed milliseconds, they are just a sequential count from 1-999 within a second. But this example demonstrates how one could build a restartable counter to memorize given state.
How it works
The code uses a counter as a surrogate for milliseconds. The counter value is appended to the time returned by the os.time()
command, and returned as a string. Should processing yield more than 999 newly generated timestamps within less than one second, the code will sleep until current second rolls over to next second and the milliseconds counter resets itself.
The magic is all done in the msec module, all that is needed to do is to call the msec.timestamp()
function, as shown:
The “milliseconds”, in this case “023”, have been appended to the time.
Sample Code
Code for main()
:
-- Example how to simulate milliseconds in timestamp require 'msec' function trace(a,b,c,d) return end function main() trace(msec.timestamp()) end
Code for the msec module:
msec ={} SQLITE_DB ='test.sqlite' conn = db.connect{ api=db.SQLITE, name=SQLITE_DB } local function zfill(s,N) if s:len() < 3 then repeat s = '0' .. s until s:len() == 3 end return s end local function Msec() -- the only configurable parameter is name of table 't' local t = 'milliseconds' local function createTable() local Sql='drop table if exists '..t conn:execute{sql=Sql,live=true} Sql = "CREATE TABLE IF NOT EXISTS "..t.." ('msec' INT(255) NULL, 'sec' INT(255) NULL);" conn:execute{sql=Sql,live=true} end local function tableExists() local rs=conn:query('SELECT name FROM sqlite_master') local function foo(i) if rs[i].name:nodeValue() == t then return true end end for i=1,#rs do if foo(i) then return true end end end local function currentSec() local rs=conn:query('SELECT * FROM '..t) if rs[1].sec:nodeValue() == os.date("%S",os.time()) then return true end end local function currentMsec() local rs=conn:query('SELECT * FROM '..t) return rs[1].msec:nodeValue() end local function writeMsec(msec) conn:execute{ sql="INSERT INTO "..t.." (msec,sec) VALUES ("..msec..", "..os.date("%S",os.time())..");", live=true } end local function updateMsec(msec) conn:execute{ sql="UPDATE "..t.." set msec="..msec..", sec="..os.date("%S",os.time())..";", live=true } end if tableExists() then local ms=currentMsec() local msnext=ms+1 if ms=='999' then repeat util.sleep(1) until os.date("%S",os.time())~=currentSec() updateMsec(1) return 1 else updateMsec(msnext) return msnext end else createTable() writeMsec(1) return 1 end end function msec.timestamp() local v = Msec() v=zfill(tostring(v),3) local t = os.date("%Y%m%d%H%M%S",os.time()) return t..v end
What’s Next?
The above example shows how to use a counter to simulate milliseconds. Just remember these are not timed milliseconds, just a count from 1-999 within a second.
If timed milliseconds needed, then solution is different. Please use OS independent solution, a call to os.clock()
, as explained in this example.
Please contact support at support@interfaceware.com if you need more help.