Time Conversion
There are several operational time functions in Lua that we can use to calculate or convert timestamps. Note that the os.* functions operate with userdata formats and os.ts.* functions operate with Unix Epoch Time formats. The os.ts.* are the standard Lua functions. See os.time, os.date, os.ts.time and os.ts.date - iNTERFACEWARE Help Center for more details on the difference between these two categories.
Below are helpful code snippets using time conversions have come up in previous support tickets:
Convert to Unix Epoch Format
local testtime = '2020-04-19 19:26:08.000'
local result = {
year=testtime:sub(1,4),
month=testtime:sub(6,7),
day=testtime:sub(9,10),
hour=testtime:sub(12,13),
min=testtime:sub(15,16),
sec=testtime:sub(18,19)
}
local time = os.ts.time(result)
local newtime = os.ts.date('%Y-%m-%d %X',tostring(time)) -- back to normal format, e.g. '2020-04-19 19:26:08'
Adding/Subtracting Time
-- Adding/subtracting time options
-- 1) Get current time or use a given time
-- Unix Epoch Time approach (recommended)
local currUnixTime = os.ts.time()
local givenUnixTime = os.ts.time(result)
-- Table approach (can be problematic if addition/subtraction affects the larger/smaller time interval
local currTableTime = os.date('*t') -- alt: os.ts.date
local givenTableTime = os.date('*t',os.time(result)) -- alt: os.ts.date and os.ts.time
-- 2) Add/Subtract (here, subtract 24 hours)
-- Unix Epoch Time approach
local newUnixTime = currUnixTime - 24*60*60 -- swap for givenUnixTime as desired
-- Table approach
local newTableTime = currTableTime -- swap for givenTableTime as desired
newTableTime.day = newTableTime.day - 1
-- 3) Convert to desired format
-- Unix Epoch Time approach
local unixToString = os.ts.date('%Y-%m-%d %I:%M:%S %p',newUnixTime) -- returns '2021-06-21 03:19:30 PM'; alt, use '*t' to convert to a table
-- Table approach
local tableToUnix = os.ts.time(newTableTime)
local tableToUserdata = os.time(newTableTime)
-- Condensed example using Unix Epoch Time approach and converting to string
local subtractedTime = os.ts.date('%Y-%m-%d %I:%M:%S %p',os.ts.time() - 24*60*60)
Convert UTC to OS Time Zone
-- Returns difference in seconds between local and utc time
-- os.difftime accounts for daylight saving: https://help.interfaceware.com/api/#os_difftime
local function getTimezoneOffset()
return os.difftime(
os.time(os.ts.date("*t")), -- local time from OS
os.time(os.ts.gmdate("*t")) -- utc time
)
end
-- Can be updated to accept any string format
local function convertToEpoch(utcDateTimeString)
return os.ts.time{
day = utcDateTimeString:sub(9,10),
month = utcDateTimeString:sub(6,7),
year = utcDateTimeString:sub(1,4),
hour = utcDateTimeString:sub(12,13),
min = utcDateTimeString:sub(15,16),
sec = utcDateTimeString:sub(18,19)
}
end
local function convertFromUtcToLocal(utcDateTimeString)
-- Offset epoch time based on time zone offset
local localEpochTime = convertToEpoch(utcDateTimeString) + getTimezoneOffset()
-- Returned format can be changed from '%c' - https://help.interfaceware.com/api/#os_ts_date
return os.ts.date('%c', localEpochTime)
end
function main()
local utcDateTimeString = '1994-11-05T13:15:30Z'
-- Accepts UTC date/time string and returns a
-- formatted date/time string in local timezone
local localDateTimeString = convertFromUtcToLocal(utcDateTimeString)
trace(localDateTimeString)
end
Get timezone offset
Accounting for DST
Generally, this is best done through the os.difftime() function with the os.ts.date() functions (as in the examples above or via the isdst flag returned from os.ts.date('*t')). However, if you are converting a given timestamp on a server in UTC (or a non-DST timezone) and no time offset details are provided, these approaches will not work as the local server time cannot be used to identify if it falls within the DST period.
In this case, the timestamp can be used to calculate whether it falls within DST.