TFM - Time Formatting Module [v. 1.0.0]

Attention User
This is not an April Fool’s joke! This TFM module is obsolete. Please consider using TFMv2 instead, which is much more powerful. Thank you!

InstantlyGetModule

If you want, you can also check out my tweet.

Greetings developers!

Happy April Fools! Today is the date of the fools, but also my first module. Have you ever had to turn a boring number of seconds to a readable and common time display format?


Well, my module does exactly this. It does all the work while you just have to write one line of code!


TFM - Time Formatting Module


More Resources

:clock10: Time Formatting Module :wrench: Array Modifier Plugin :books: ListLib

Overview

The timing of this release is perfect, isn’t it? You’d be a fool if you think otherwise!

BAM! Double joke!

Anyways, I plan to make a series of modules (similar to @Elttob), with the series being called “Crazy Cool Carbyne Collection” also known as “Quad-C”.


API

Currently, TFM has an extremely simple API primarily because it is very new and because it is my first module.

tfm:Convert(integer Seconds, string Form, bool AddZero)

Seconds (MANDATORY)

An integer representing the number of seconds you want to convert.

Form (Optional)

A string that controls how the given seconds will be formatted and displayed.

Currently, there are three forms:
Default (aka Colon):

  • automatically set if the parameter is not given
  • displays as 00:00:00
  • max unit is hour (i.e. 24 hours is not the limit you can have something like 32:02:13)
  • supports the AddZero parameter
  • accepted strings: “default” and “colon” in any case (i.e. all or partial capitalization is accepeted)

Short:

  • displays as 00 yr(s) 00 mon 00 d 00 hr(s) 00 min(s) 00 sec
  • max unit is year (I originally wanted to extend to millennium, but that’s redundant!)
  • adjusts to plural (yrs, hrs, mins ONLY)
  • accepted strings: “short” in any case

Full:

  • displays as 00 year(s) 00 month(s) 00 day(s) 00 hour(s) 00 minute(s) 00 second(s)
  • max unit is year (will always be the same as the short form)
  • adjusts to plural (all units)
  • accepted strings: “full” in any case
AddZero (Optional)

A boolean value denoting whether or not you would like to toggle a zero in front of the current largest unit.

For example:
Setting this to true will display 3690 as 01:01:30. Setting this to false will result in 1:01:30. Note: only the zero in the biggest unit (in this case, hour) toggled, not the minute.


Get the Module


Thoughts and Feedback

As I mentioned before, this is my first module, so there may be some bugs (even though I tested this a million times with loops). Also, you may find my coding style a little messy or you may have a suggestion on how to further optimize it. Or, you may even want to request a new feature or change an existing one.

In any of these instances, feel free to PM me via the DevForums only or reply to this topic. I am not the best scripter, so please be patient with me! However, I am always looking for ways to improve.

Of course, I cannot post anything without … polls!

How useful is this module to you?

  • Very useful
  • Useful
  • Neutral
  • Not very useful
  • Not useful whatsoever

0 voters

Please only answer this after using the module: How is your overall experience with it? Rate from 1-10.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

0 voters


Thank you for your time and feedback,
and don’t get fooled today!

42 Likes

So I took a stab at creating my own TFM module, this 125-line monstrosity is the result.

In short, the biggest change I made was using way more for loops and way more usage of the string and table library.

local CONVERSIONS = {
	12, -- years to months
	30, -- months to days
	24, -- days to hours
	60, -- hours to minutes
	60, -- minutes to seconds
}

local INDEXES = {y = 1, M = 2, d = 3, h = 4, m = 5, s = 6}

local SHORT_UNITS = {"yr", "mon", "d", "hr", "min", "sec"}
local SHORT_PLURALS = {[1] = true, [4] = true, [5] = true}

local FULL_UNITS = {"year", "month", "day", "hour", "minute", "second"}

local TFM = {}

--[[**
	Takes an amount of time (in seconds) and converts it to a string
	
	@param [t:integer] Seconds   "An integer representing the number of seconds you want to convert."
	@param [t:string] Form   "A string that controls how the given seconds will be formatted and displayed."
	@param [t:boolean] AddZero      "A boolean value denoting whether or not you would like to toggle a zero in front of the current largest unit."
**--]]
function TFM.Convert(Seconds, Form, AddZero)
	
	do -- input validation
		local type_Seconds = typeof(Seconds)
		assert(type_Seconds == 'number', 
			"ShortenedTFM: Seconds (arg 1) is not of type 'number'!")
		assert(Seconds%1 == 0,
			"ShortenedTFM: Seconds (arg 1) is not an integer!")
		
		local type_Form = typeof(Form)
		assert(type_Form == 'string' or type_Form == 'nil', 
			"ShortenedTFM: Form (arg 2) is not of type 'string' or 'nil'!")
		
		local type_AddZero = typeof(AddZero)
		assert(type_AddZero == 'boolean' or type_AddZero == 'nil', 
			"ShortenedTFM: AddZero (arg 3) is not of type 'boolean' or 'nil'!")
	end
	
	local firstValue
	local timeValues = {} do -- integer values for each unit of time
		for i = 1, 6 do
			local divisor = 1
			for j = i, 5 do
				divisor *= CONVERSIONS[j]
			end
			
			local result = math.floor(Seconds/divisor)
			if i > 1 then
				result %= CONVERSIONS[i - 1]
			end
			
			if not firstValue and result ~= 0 then
				firstValue = i
			end
			timeValues[i] = result
		end
	end
	firstValue = firstValue or 6
			
	local form = Form and string.lower(Form)
	
	local result
	if form == "short" then -- 00 yr(s) 00 mon 00 d 00 hr(s) 00 min(s) 00 sec
		local formatTable = {
			(AddZero and "%02d " or "%d ") 
				.. SHORT_UNITS[firstValue] 
				.. (SHORT_PLURALS[firstValue] and timeValues[firstValue] ~= 1 and "s " or " ")
		}
		for i = firstValue + 1, 6 do
			formatTable[#formatTable + 1] = "%02d " 
				.. SHORT_UNITS[i] 
				.. (SHORT_PLURALS[i] and timeValues[i] ~= 1 and "s " or " ")
		end
		
		result = string.format(table.concat(formatTable):sub(1, -2), table.unpack(timeValues, firstValue, 6))
	elseif form == "full" then -- 00 year(s) 00 month(s) 00 day(s) 00 hour(s) 00 minute(s) 00 second(s)
		local formatTable = {
			(AddZero and "%02d " or "%d ")
				.. FULL_UNITS[firstValue]
				.. (timeValues[firstValue] ~= 1 and "s " or " ")
		}
		for i = firstValue + 1, 6 do
			formatTable[#formatTable + 1] = "%02d " 
				.. FULL_UNITS[i] 
				.. (timeValues[i] ~= 1 and "s " or " ")
		end
			
		result = string.format(table.concat(formatTable):sub(1, -2), table.unpack(timeValues, firstValue, 6))
	elseif Form then -- custom format string
		local params = {}
		local subs = {}
		
		for parameter in string.gmatch(Form, "%%[0 '+-]*%d*([yMdhms])") do
			params[#params + 1] = INDEXES[parameter]
		end
		
		local largestUnit = math.min(6, table.unpack(params))
		local divisor = 1
		for i = largestUnit, 5 do
			divisor *= CONVERSIONS[i]
		end
		timeValues[largestUnit] = math.floor(Seconds/divisor)
		
		for _, index in ipairs(params) do
			subs[#subs + 1] = timeValues[index]
		end
		
		local formatString = string.gsub(Form, "(%%[0 '+-]*%d*)[yMdhms]", "%1d")
		
		result = string.format(formatString, table.unpack(subs))
	else -- 00:00:00
		local formatString = (AddZero and "%02d" or "%d") .. string.rep(":%02d", math.min(6 - firstValue, 2))
		
		timeValues[4] = math.floor(Seconds/3600) -- used to show hours without extra units
		result = string.format(formatString, table.unpack(timeValues, math.max(firstValue, 4), 6))
	end
	
	return result, timeValues
end

return TFM

I also created an extra formatting option if none of the other options matched specifically for string.format behavior. It’s strikingly similar, except it looks for 6 special format characters:

  • %y - Years
  • %M - Months
  • %d - Days
  • %h - Hours
  • %m - Minutes
  • %s - Seconds

And the function then replaces them with the value they are supposed to have. It has support for integer formatters just like normal %d does, which means you can use more custom formatting options, like:

TFM.Convert(7200, "Time Left: %+6m: %02s") --> "Time Left: +120  : 00"

It also returns an array of values in the order of the format characters up there, since I deemed that useful too.

11 Likes

This module is very nice. Thank you! I found a very nice use for it while scripting potion boosters for my game.

1 Like

This is really cool!
Nice work!

1 Like