Skip to content
Engine

Runtime

TimeService

Scaled game time you can pause and speed up, a day/night cycle with seasons and weekdays, timers on game time, and real-world dates.

ServiceShared

Getting it

local TimeService = Engine:GetService("TimeService")

Overview

TimeService keeps a game clock that is separate from real time. Set TimeScale to 2 and game time runs twice as fast; pause it and it stops. Timers created through TimeService follow the game clock, so a 10-second ability cooldown really takes 5 seconds of real time at double speed, and freezes while the game is paused.

On top of the game clock it runs a day/night cycle: a 24-hour in-game day that lasts DayLength real minutes, with sunrise and sunset, seasons, weekdays and an optional link to Lighting.ClockTime.

A day/night cycle in three lines
local TimeService = Engine:GetService("TimeService")

TimeService.DayLength = 20            -- one in-game day takes 20 real minutes
TimeService.AutoDayNightEnabled = true -- drive Lighting.ClockTime

TimeService:OnClockTime(18, function()
	print("Sunset - lights on")
	turnOnStreetLights()
end)

Important

Each side (server, and every client) keeps its own clock. Only the server may change time (TimeScale, Paused, TimeOfDay and the other settings); calling a setter on the client raises an error. Values are not synced to clients automatically, so if clients need the exact game time, send it to them, for example with NetworkService.

Game time

Now

TimeService:Now(): number

Game seconds elapsed, affected by TimeScale and pausing.

RealNow

TimeService:RealNow(): number

Real seconds (os.clock()), never scaled.

SetTimeScale

TimeService:SetTimeScale(scale: number, tweenTime: number?)

Changes the speed of game time, smoothly over tweenTime real seconds when given. Server only.

-- Bullet-time for 3 seconds
TimeService:SetTimeScale(0.25, 0.3)
task.delay(3, function()
	TimeService:SetTimeScale(1, 0.5)
end)

Pause / Resume

TimeService:Pause()
TimeService:Resume()

Stops and continues game time. Server only.

TimeScaleChanged

TimeService.TimeScaleChanged: Signal<number>

Fires with the new scale whenever it changes, including every step of a tween.

Timers on game time

All three return a Timer Task with :Cancel() and Paused.

MethodDescription
TimeService:After(seconds, fn)Runs fn after seconds of game time.
TimeService:Every(seconds, fn)Runs fn every seconds of game time.
TimeService:Schedule(atGameTime, fn)Runs fn when :Now() reaches atGameTime.

CreateClock

TimeService:CreateClock(name: string): GameClock

An extra, independent clock with its own scale and pause, for example a slowed-down zone or a minigame. It has :Now(), :SetTimeScale(scale), :GetTimeScale(), :Pause(), :Resume(), :After(seconds, fn), :Every(seconds, fn) and a read-only Name.

Day and night

OnClockTime

TimeService:OnClockTime(hours: number, fn: () -> ()): ClockTimeHandle

Calls fn every in-game day when the clock reaches hours (0-24, decimals allowed: 6.5 is 06:30). The handle has :Cancel().

IsDayTime / IsNightTime

TimeService:IsDayTime(): boolean
TimeService:IsNightTime(): boolean

Whether the clock is between SunriseHour and SunsetHour.

TimeOfDayChanged

TimeService.TimeOfDayChanged: Signal<number>

Fires with the hour when TimeOfDay is set, and once per in-game minute while AutoDayNightEnabled is on.

Calendar

The calendar counts in-game days from the moment the day/night clock started. A year has four seasons of SeasonLength days each.

MethodReturns
:GetDate(){ day, season, year }, each starting at 1. day is the day within the season.
:GetSeasonName()The current name from SeasonNames, by default Spring, Summer, Autumn, Winter.
:GetSeasonProgress()0 to 1 through the current season.
:GetWeekday()1 to 7.
:GetWeekdayName()The current name from WeekdayNames, by default Monday to Sunday.

Properties

Read anywhere, set on the server only.

PropertyDescription
TimeScale: numberSpeed of game time. Setting it cancels a running tween.
Paused: booleanWhether game time is paused.
TimeOfDay: numberCurrent in-game hour, 0 to 24. Set it to jump to a time.
DayLength: numberReal minutes per in-game day. Changing it keeps the current time of day.
SunriseHour, SunsetHour: numberWhen day and night begin.
AutoDayNightEnabled: booleanWrites TimeOfDay to Lighting.ClockTime ten times per second.
SeasonLength: numberIn-game days per season (at least 1).
SeasonNames: { string }Exactly four names.
WeekdayNames: { string }Exactly seven names.

Real-world time

For daily rewards, events and timestamps.

MethodDescription
:IRLNow()Unix timestamp in seconds (os.time()).
:IRLElapsed(since, upTo?)Seconds between two timestamps, up to now by default.
:IRLNowAt(offsetHours)The timestamp shifted by a time-zone offset.
:GetIRLDate(utc?, timestamp?)A date table { year, month, day, hour, min, sec, wday, yday, isdst }, local or UTC.
:FormatIRLDate(format, timestamp?)os.date formatting, such as "%Y-%m-%d".
:FormatDuration(seconds, style?)Readable durations.
TimeService:FormatDuration(3725)          --> "1:02:05"
TimeService:FormatDuration(3725, "short") --> "1h 2m"
TimeService:FormatDuration(3725, "long")  --> "1 hour 2 minutes 5 seconds"

Configuration

Defaults from DefaultConfiguration/Services/TimeService6 settings
SettingDefaultWhat it does
DefaultTimeScale1Initial TimeScale; 1 is real time, 2 is twice as fast.
DefaultDayLengthMinutes24Real minutes per in-game day.
DefaultSeasonLengthDays7In-game days per season.
DefaultSunriseHour6In-game hour the day phase starts.
DefaultSunsetHour18In-game hour the night phase starts.
TweenStepSeconds1 / 30How often :SetTimeScale(scale, tweenTime) re-samples while tweening.

Types

export type DurationStyle = "colon" | "short" | "long"
export type DateInfo = { read day: number, read season: number, read year: number }
export type IRLDate
export type ClockTimeHandle
export type Properties