local datetime = {} function datetime._format_time(t, fmt, mode) if mode == "12h" then local hour = t.hour local ampm = "AM" if hour == 0 then hour = 12 elseif hour == 12 then ampm = "PM" elseif hour > 12 then hour = hour - 12 ampm = "PM" end -- if fmt does not valid, use default format for 12h if not fmt or fmt == "" then fmt = "%02d:%02d:%02d %s" end return string.format(fmt, hour, t.min, t.sec, ampm) else -- if fmt does not valid, use default format for 24h if not fmt or fmt == "" then fmt = "%02d:%02d:%02d" end return string.format(fmt, t.hour, t.min, t.sec) end end -- Validate and return timezone offset (must be a number) function datetime.get_offset(timezone_offset) local n = tonumber(timezone_offset) if n then return n end return 0 end -- Returns a table with current UTC time function datetime.utcnow() return os.date("!*t") end -- Returns a table with current local time function datetime.localtime() return os.date("*t") end function datetime.now(timezone_offset) local o = datetime.get_offset(timezone_offset) if o == 0 then -- Local time return os.date("*t") else -- Current UTC time local utc = os.time(os.date("!*t")) -- Offset local target = utc + o * 3600 return os.date("*t", target) end end -- mode: "12h" or "24h" (required) -- fmt: string.format pattern, e.g. "%02d:%02d:%02d %s" for 12h, "%02d:%02d:%02d" for 24h function datetime.format(timezone_offset, fmt, mode) assert(mode == "12h" or mode == "24h", "mode must be '12h' or '24h'") local o = datetime.get_offset(timezone_offset) local t = datetime.now(o) return datetime._format_time(t, fmt, mode) end -- Returns seconds since midnight for a given timezone offset function datetime.seconds_since_midnight(timezone_offset) local t = datetime.now(timezone_offset) return t.hour * 3600 + t.min * 60 + t.sec end -- Returns weekday (0=Sunday, 6=Saturday) for a given timezone offset function datetime.weekday(timezone_offset) local t = datetime.now(timezone_offset) return t.wday - 1 end return datetime