Time Module
The time module provides comprehensive date and time manipulation utilities for Lua scripts. All timestamps are exchanged as ISO8601 strings for consistency and timezone awareness.
Time Format
All time values use ISO8601 format:
- UTC time:
"2024-01-15T14:30:45.123456Z" - Local time with offset:
"2024-01-15T14:30:45.123456-05:00"
Functions
Current Time
time.now()
Returns the current local time as an ISO8601 string.
local current = time.now()
print(current) -- "2024-01-15T14:30:45.123456-05:00"time.utc_now()
Returns the current UTC time as an ISO8601 string.
local utc = time.utc_now()
print(utc) -- "2024-01-15T19:30:45.123456Z"Time Parsing and Validation
time.parse(timestamp)
Parses and validates an ISO8601 timestamp string.
Parameters:
timestamp(string): ISO8601 formatted timestamp
Returns:
- Valid ISO8601 string on success
niland error message on failure
local valid = time.parse("2024-01-15T14:30:45Z")
local invalid, err = time.parse("not a date")
if not invalid then
print("Error:", err)
endTime Manipulation
time.add(timestamp, seconds)
Adds or subtracts seconds from a timestamp.
Parameters:
timestamp(string): ISO8601 timestampseconds(number): Seconds to add (negative to subtract)
local now = time.utc_now()
local hour_later = time.add(now, 3600)
local hour_ago = time.add(now, -3600)time.add_minutes(timestamp, minutes)
Adds or subtracts minutes from a timestamp.
local meeting = "2024-01-15T14:00:00Z"
local delayed = time.add_minutes(meeting, 30) -- 14:30time.add_hours(timestamp, hours)
Adds or subtracts hours from a timestamp.
local start = "2024-01-15T09:00:00Z"
local lunch = time.add_hours(start, 3.5) -- 12:30time.add_days(timestamp, days)
Adds or subtracts days from a timestamp.
local today = time.utc_now()
local next_week = time.add_days(today, 7)
local yesterday = time.add_days(today, -1)time.shift(timestamp, options)
Shifts a timestamp by multiple time units simultaneously.
Parameters:
timestamp(string): ISO8601 timestampoptions(table): Table with time units as keysyears: Number of years to addmonths: Number of months to add (approximated as 30 days)weeks: Number of weeks to adddays: Number of days to addhours: Number of hours to addminutes: Number of minutes to addseconds: Number of seconds to add
local start = "2024-01-15T12:00:00Z"
local shifted = time.shift(start, {
days = 1,
hours = 2,
minutes = 30
})
print(shifted) -- "2024-01-16T14:30:00Z"Time Comparison
time.compare(timestamp1, timestamp2)
Compares two timestamps.
Returns:
-1if timestamp1 is earlier than timestamp20if timestamps are equal1if timestamp1 is later than timestamp2
local past = "2024-01-14T12:00:00Z"
local future = "2024-01-16T12:00:00Z"
print(time.compare(past, future)) -- -1
print(time.compare(future, past)) -- 1
print(time.compare(past, past)) -- 0time.diff(timestamp1, timestamp2, unit)
Calculates the difference between two timestamps.
Parameters:
timestamp1(string): First timestamptimestamp2(string): Second timestampunit(string, optional): Unit of measurement ("seconds", "minutes", "hours", "days"). Default: "seconds"
Returns: The difference as a number (timestamp2 - timestamp1)
local start = "2024-01-15T09:00:00Z"
local end = "2024-01-15T17:30:00Z"
local hours = time.diff(start, end, "hours")
print(hours) -- 8.5
local minutes = time.diff(start, end, "minutes")
print(minutes) -- 510time.before(timestamp1, timestamp2)
Checks if timestamp1 is before timestamp2.
local past = "2024-01-14T12:00:00Z"
local future = "2024-01-16T12:00:00Z"
print(time.before(past, future)) -- true
print(time.before(future, past)) -- falsetime.is_after(timestamp1, timestamp2)
Checks if timestamp1 is after timestamp2.
local past = "2024-01-14T12:00:00Z"
local future = "2024-01-16T12:00:00Z"
print(time.is_after(future, past)) -- true
print(time.is_after(past, future)) -- falseTime Conversion
time.to_unix(timestamp)
Converts an ISO8601 timestamp to Unix time (seconds since epoch).
local ts = "2024-01-15T12:00:00Z"
local unix = time.to_unix(ts)
print(unix) -- 1705320000time.from_unix(unix_timestamp)
Converts Unix time to an ISO8601 timestamp.
local unix = 1705320000
local ts = time.from_unix(unix)
print(ts) -- "2024-01-15T12:00:00Z"time.to_date(timestamp)
Extracts the date portion from a timestamp.
local ts = "2024-01-15T14:30:45.123456Z"
local date = time.to_date(ts)
print(date) -- "2024-01-15"time.to_time(timestamp)
Extracts the time portion from a timestamp.
local ts = "2024-01-15T14:30:45.123456Z"
local time_part = time.to_time(ts)
print(time_part) -- "14:30:45.123456"Time Formatting
time.format(timestamp, format_string)
Formats a timestamp using a format string.
Format Specifiers:
%Y- Year (4 digits)%m- Month (01-12)%d- Day of month (01-31)%H- Hour (00-23)%M- Minute (00-59)%S- Second (00-59)%a- Short weekday name (Mon, Tue, etc.)%A- Full weekday name (Monday, Tuesday, etc.)%b- Short month name (Jan, Feb, etc.)%B- Full month name (January, February, etc.)%z- Timezone offset (+00:00)%Z- Timezone name
local ts = "2024-01-15T14:30:45Z"
print(time.format(ts, "%Y-%m-%d")) -- "2024-01-15"
print(time.format(ts, "%H:%M:%S")) -- "14:30:45"
print(time.format(ts, "%A, %B %d, %Y")) -- "Monday, January 15, 2024"
print(time.format(ts, "%a %b %d %H:%M:%S")) -- "Mon Jan 15 14:30:45"Time Boundaries
time.start_of_day(timestamp)
Returns the beginning of the day for the given timestamp.
local ts = "2024-01-15T14:30:45Z"
local start = time.start_of_day(ts)
print(start) -- "2024-01-15T00:00:00Z"time.end_of_day(timestamp)
Returns the end of the day for the given timestamp.
local ts = "2024-01-15T14:30:45Z"
local end_day = time.end_of_day(ts)
print(end_day) -- "2024-01-15T23:59:59.999999Z"time.start_of_month(timestamp)
Returns the beginning of the month for the given timestamp.
local ts = "2024-01-15T14:30:45Z"
local start = time.start_of_month(ts)
print(start) -- "2024-01-01T00:00:00Z"time.end_of_month(timestamp)
Returns the end of the month for the given timestamp.
local ts = "2024-01-15T14:30:45Z"
local end_month = time.end_of_month(ts)
print(end_month) -- "2024-01-31T23:59:59.999999Z"time.start_of_week(timestamp, start_day)
Returns the beginning of the week for the given timestamp.
Parameters:
timestamp(string): ISO8601 timestampstart_day(string, optional): Day the week starts on ("monday", "sunday", etc.). Default: "monday"
local ts = "2024-01-17T14:30:45Z" -- Wednesday
local monday = time.start_of_week(ts)
print(monday) -- "2024-01-15T00:00:00Z"
local sunday = time.start_of_week(ts, "sunday")
print(sunday) -- "2024-01-14T00:00:00Z"time.end_of_week(timestamp, start_day)
Returns the end of the week for the given timestamp.
local ts = "2024-01-17T14:30:45Z" -- Wednesday
local sunday = time.end_of_week(ts)
print(sunday) -- "2024-01-21T23:59:59.999999Z"
local saturday = time.end_of_week(ts, "sunday")
print(saturday) -- "2024-01-20T23:59:59.999999Z"Practical Examples
Date Range Generation
function generate_date_range(start_date, days)
local dates = {}
for i = 0, days - 1 do
local date = time.add_days(start_date, i)
table.insert(dates, time.to_date(date))
end
return dates
end
local week = generate_date_range("2024-01-15T00:00:00Z", 7)
-- {"2024-01-15", "2024-01-16", ..., "2024-01-21"}Business Hours Check
function is_business_hours(timestamp)
local time_str = time.to_time(timestamp)
local hour = tonumber(string.sub(time_str, 1, 2))
-- Check if it's a weekday
local day_name = time.format(timestamp, "%A")
local is_weekday = day_name ~= "Saturday" and day_name ~= "Sunday"
-- Business hours: 9 AM to 5 PM on weekdays
return is_weekday and hour >= 9 and hour < 17
end
local office_time = "2024-01-15T10:30:00Z" -- Monday 10:30 AM
local weekend = "2024-01-20T10:30:00Z" -- Saturday 10:30 AM
print(is_business_hours(office_time)) -- true
print(is_business_hours(weekend)) -- falseAge Calculation
function calculate_age(birth_date, current_date)
local days = time.diff(birth_date, current_date, "days")
local years = math.floor(days / 365.25) -- Account for leap years
return years
end
local birth = "1990-05-15T00:00:00Z"
local today = time.utc_now()
local age = calculate_age(birth, today)
print("Age:", age, "years")Deadline Tracking
function days_until_deadline(deadline)
local now = time.utc_now()
if time.is_after(now, deadline) then
return 0, "Deadline has passed"
end
local days = time.diff(now, deadline, "days")
if days < 1 then
local hours = time.diff(now, deadline, "hours")
return hours, "hours remaining"
end
return days, "days remaining"
end
local project_due = "2024-02-01T17:00:00Z"
local remaining, unit = days_until_deadline(project_due)
print(string.format("%.1f %s", remaining, unit))Recurring Events
function next_occurrence(start_date, interval_days)
local now = time.utc_now()
local current = start_date
-- Find the next occurrence after now
while time.before(current, now) do
current = time.add_days(current, interval_days)
end
return current
end
-- Weekly meeting every Monday at 10 AM
local first_meeting = "2024-01-01T10:00:00Z" -- A Monday
local next_meeting = next_occurrence(first_meeting, 7)
print("Next meeting:", time.format(next_meeting, "%A, %B %d at %H:%M"))Time Zone Aware Operations
function schedule_across_timezones(utc_time)
-- Format times for different regions
local schedule = {
UTC = time.format(utc_time, "%H:%M %Z"),
-- Note: Actual timezone conversion would require additional logic
-- This is a simplified example
Eastern = time.format(time.add_hours(utc_time, -5), "%H:%M EST"),
Pacific = time.format(time.add_hours(utc_time, -8), "%H:%M PST"),
Tokyo = time.format(time.add_hours(utc_time, 9), "%H:%M JST")
}
return schedule
end
local meeting = "2024-01-15T15:00:00Z"
local times = schedule_across_timezones(meeting)
for zone, time_str in pairs(times) do
print(zone .. ":", time_str)
endError Handling
All time functions return nil and an error message when given invalid input:
local result, error = time.parse("invalid date")
if not result then
print("Error:", error) -- "Error: invalid"
end
-- Safe time operations
function safe_add_days(timestamp, days)
local result, err = time.add_days(timestamp, days)
if not result then
print("Failed to add days:", err)
return timestamp -- Return original on error
end
return result
endBest Practices
Always validate timestamps before operations:
lualocal function process_timestamp(ts) local valid = time.parse(ts) if not valid then return nil, "Invalid timestamp" end -- Process valid timestamp return time.add_hours(valid, 1) endUse UTC for storage and calculations:
lua-- Store as UTC local event_time = time.utc_now() cache.put("event_timestamp", event_time) -- Convert for display local stored = cache.get("event_timestamp") local formatted = time.format(stored, "%Y-%m-%d %H:%M:%S %Z")Handle timezone offsets consistently:
lua-- Preserve timezone information local user_time = "2024-01-15T14:30:00-05:00" local shifted = time.add_hours(user_time, 2) -- Result maintains the -05:00 offsetUse appropriate time units:
lua-- For short durations, use seconds or minutes local process_time = time.diff(start_time, end_time, "seconds") -- For longer periods, use days local project_duration = time.diff(project_start, project_end, "days")Cache formatted strings for repeated use:
lualocal function get_formatted_time(timestamp, format) local cache_key = "formatted:" .. timestamp .. ":" .. format local cached = cache.get(cache_key) if cached then return cached end local formatted = time.format(timestamp, format) cache.put_ttl(cache_key, formatted, 300) -- Cache for 5 minutes return formatted end