papierbak
papierbak

Reputation: 21

Parse time string to hours, minutes and seconds in Lua

I am currently working on a plugin for grandMA2 lighting control using Lua. I need the current time. The only way to get the current time is the following function:

gma.show.getvar('TIME')

which always returns the current system time, which I then store in a variable. An example return value is "12h54m47.517s".

How can I separate the hours, minutes and seconds into 3 variables?

Upvotes: 2

Views: 1055

Answers (2)

koyaanisqatsi
koyaanisqatsi

Reputation: 2813

Lets do it with string method gsub()

local ts = gma.show.getvar('TIME')
local hours = ts:gsub('h.*', '')
local mins = ts:gsub('.*%f[^h]', ''):gsub('%f[m].*', '')
local secs = ts:gsub('.*%f[^m]', ''):gsub('%f[s].*', '')

To make a Timestring i suggest string method format()

-- secs as float
timestring = ('[%s:%s:%.3f]'):format(hours, mins, secs)
-- secs not as float
timestring = ('[%s:%s:%.f]'):format(hours, mins, secs)

Upvotes: 1

Luatic
Luatic

Reputation: 11191

If os.date is available (and matches gma.show.getvar('TIME')), this is trivial:

If format starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if format is the string "*t", then date returns a table with the following fields: year, month (1–12), day (1–31), hour (0–23), min (0–59), sec (0–61, due to leap seconds), wday (weekday, 1–7, Sunday is 1), yday (day of the year, 1–366), and isdst (daylight saving flag, a boolean). This last field may be absent if the information is not available.

local time = os.date('*t')
local hour, min, sec = time.hour, time.min, time.sec

This does not provide you with a sub-second precision though.

Otherwise, parsing the time string is a typical task for tostring and string.match:

local hour, min, sec = gma.show.getvar('TIME'):match('^(%d+)h(%d+)m(%d*%.?%d*)s$')
-- This is usually not needed as Lua will just coerce strings to numbers
-- as soon as you start doing arithmetic on them;
-- it still is good practice to convert the variables to the proper type though
-- (and starts being relevant when you compare them, use them as table keys or call strict functions that check their argument types on them)
hour, min, sec = tonumber(hour), tonumber(min), tonumber(sec)

Pattern explanation:

  • ^ and $ pattern anchors: Match the full string (and not just part of it), making the match fail if the string does not have the right format.
  • (%d)+h: Capture hours: One or more digits followed by a literal h
  • (%d)+m: Capture minutes: One or more digits followed by a literal m
  • (%d*%.?%d*)s: Capture seconds: Zero or more digits followed by an optional dot followed by again zero or more digits, finally ending with a literal s. I do not know the specifics of the format and whether something like .1s, 1.s or 1s is occasionally emitted, but Lua's tonumber supports all of these so there should be no issue. Note that this is slightly overly permissive: It will also match . (just a dot) and an s without any leading digits. You might want (%d+%.?%d+)s instead to force digits appearing before & after the dot.

Upvotes: 3

Related Questions