Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
number to time-String — Gideros Forum

number to time-String

HolonistHolonist Member
edited May 2015 in Code snippets
I wrote a clock utility that lets you input a number and converts it to a string.

I'm fairly excited about this as it's the first utility i wrote which is highly customizable by parameters.
Also, it's the first time I used recursion to solve a problem (i.e. filling up the substrings with zeroes / computing the total weight of a unit anywhere in the list).

I know this is probably useless because a specific time-to-string-machine would be much easier to code and especially much more performant, but maybe someone likes it.

Commentary not included since getting this to work was kind of magic to me.
I'm ready to answer any questions though.

Let me know what you think.



examples:

1) clock.to(someInt, {1, 255, 255}, {3, 3, 3}, ":")

- display: 000:000:000
- values (from right to left): 2) clock.to(someInt, {1, 1000, 60, 60, 24}, {3, 2, 2, 2, 3}, " - ")

- display: 000 - 00 - 00 - 00 - 000
- values (from right to left): code (clock.lua)
--last updated: 2015-06-05 15:23
--author: holonist
 
clock = {}
--[[
_time:int
_params:int[]
_digits:int[]
_seperator:String
]]
clock.to = function (_time, _params, _digitVals, _seperator)
 
	local time = _time
 
	local params = _params
	local digitVals = _digitVals
	local seperator = _seperator
 
	if params == nil then
		params = {1, 60, 60, 24}
	end
 
	if digitVals == nil then
		digitVals = {3, 2, 2, 3}
	end
 
	if seperator == nil then
		seperator = ":"
	end
 
	--the string we are going to return in the end.
	local clockString = ""
 
	--save all sub-time-units (ie seconds, minutes, ...) in subStrings
	local subStrings = {}
 
	for i=1, #params do
 
		if i<#params then
			subStrings[i] = tostring(math.floor(math.fmod(time/clock.getmod(params[i], params, i),params[i+1])))
		else
			subStrings[i] = tostring(math.floor(math.fmod(time/clock.getmod(params[i], params, i),100000000)))
		end
 
	end
 
	for i=1, #subStrings do
 
		--if the substrings contain less chars then designated in digitVals, add zeros
		subStrings[i] = clock.fillup(subStrings[i], digitVals[i])
 
	end
 
	for i=#subStrings, 1, -1 do
 
		clockString = clockString..subStrings[i]
		if i > 1 then clockString = clockString..seperator end
 
	end
 
	return clockString
 
end
 
clock.fillup = function(str, di)
 
	if str:len() < di then
		return clock.fillup("0"..str, di)
	else
		return str
	end
 
end
 
clock.getmod = function(mod, params, index)
 
	if index > 1 then
 
		mod = mod*params[index-1]
		return clock.getmod(mod, params, index-1)
 
	else
		return mod
	end
 
end
edit: fixed some irritating stuff in the code
edit2: updated the code, updated examples, added video below examples.

Likes: talis, hgy29

+1 -1 (+2 / -0 )Share on Facebook

Comments

  • piepie Member
    thanks for sharing @Holonist almost everything could come in handy sooner or later :)
    I didn't look over it enough, however if "first unit" must always have value 1 you could set it by default inside the function to save up the 1 when calling it.

    For standard time units you can also use os.date()
    http://www.lua.org/pil/22.1.html
     local dateTime = tostring(os.date("%Y%m%d%H%M%S"))

    Likes: Holonist

    +1 -1 (+1 / -0 )Share on Facebook
  • HolonistHolonist Member
    edited May 2015
    Yes I thought about somehow leaving the 1 to the function, but for some reason I wasn't able to imagine how I would have to change the code accordingly.

    Also, I'm calling clock.getmod(paramlist[i], paramlist, i) two times. Now it seems obvious to me that the function should work without the first parameter.

    Still some work to do.
    Can you hand an arbitrary value to os.date() to format it, or does it always give back the actual time?

    Likes: talis

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    edited May 2015
    @Holonist you can give arbitrary values, is everything written at the provided link :)
    As an example: os.date on 906000490 and its output "back in time values"
     
    local date_return_string = os.date("%x %X", 906000490)
    local date_return_table = os.date("*t", 906000490) --"*t" returns {year = 1998, month = 9, day = 16, yday = 259, wday = 4,hour = 23, min = 48, sec = 10}
    print(date_return_string, date_return_table , os.time(date_return_table))
    I don't have much time now to study your work, but you can use ipairs instead of doing "for i =1, ... blah blah" as in:
    for i,plist in ipairs(paramlist) do
     
    		if i<#paramlist then
    			subStrings[i] = tostring(math.floor(math.fmod(time/clock.getmod(plist, paramlist, i),paramlist[i+1])))
    		else
    			subStrings[i] = tostring(math.floor(math.fmod(time/clock.getmod(plist, paramlist, i),100000000)))
    		end
     
    	end
     
    	for i,sstr in ipairs(subStrings) do
     
    		--if the substrings contain less chars then designated in digits, add zeros
    		subStrings[i] = clock.fillup(sstr, digits)
     
    	end

    you were already doing a for loop, but with ipairs you don't need to read the data again (plist and sstr instead of paramlist[i] and subStrings[i] ) - maybe this could help getting rid of the 1 ? -I'm guessing, I didn't check it.
    Notice that you can use ipairs because you don't have ["string-indices"]. (if you had them you could have used "pairs").

    Also I think that you can "localize" clock.fillup and clock.mod, placing them inside clock.to() - which then could simply become: function clockTo(pTime, pParams, pDigits) .

    Without changing too much code I would write:
    function clockTo(pTime, pParams, pDigits)
    	local clockf = {}
    	clockf.fillup = function(str, digits)
     
    			if str:len() < digits then
    				return clockf.fillup("0"..str, digits)
    			else
    				return str
    			end
     
    		end
     
    clockf.getmod = function(mod, paramlist, index)
     
    			if index > 1 then
     
    				mod = mod*paramlist[index-1]
    				return clockf.getmod(mod, paramlist, index-1)
     
    			else
    				return mod
    			end
     
    		end
    -- and everything else...
    of course, then you would have to update any other reference inside clock.to().

    As far as I understood: the most you can keep local, the faster your app would perform.
  • I didn't know you could define functions inside a function. Will give it a try.

    Well that os.date() thing makes my work pretty obsolete. The only advantage my function has , it's not bound to certain time units.

    For the for-loops, I simply like them. I am familiar with pairs and ipairs, but imo they aren't needed here. I also think they are a bit slower than straight for-loops, but could be wrong.

    Anyway thanks for the insights. I'll keep changing that thing until it's perfect, seems like a good exercise
  • totebototebo Member
    Nice! Thanks for sharing!
    My Gideros games: www.totebo.com
  • HolonistHolonist Member
    edited May 2015
    Is there some kind of limitation that you can only pass one table to a function?
    clock.to = function (_time, _params, _digitVals, _seperator)
     
    	print(_digitVals[3])
    	...
    end
     
    clock.to(10, {1,2,3}, {1,2,3}, ":")
    -> error: attempt to index local '_digitVals' (a number value)
    why on earth would _digitVals be recognized as a number? it is clearly a table, just like _params.
  • HolonistHolonist Member
    edited May 2015
    also, print(_separator) returns nil when I print(_digitVals[3]) before. Otherwise, it returns ":", as expected.

    Ok I'm retarded, I forgot to remove print("59s: "..clock.to(59, {1, 60, 60, 24}, 2)) from another file, where it still uses the old function.
Sign In or Register to comment.