How to create a clock time system

I just wanted to share how I implemented a clock system in Roblox. First, this script requires a RemoteEvent named to process correctly parented under a Folder named in ReplicatedStorage.

This is particularly useful for games that require time awareness while also being able to fast forward the time when needed and stop the time depending on the situation. Let me know how you would have done it and any ideas I can add to make it more efficient.
Cheers mate!

-- Created by: sHin_7823
-- Services needed
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")

local RunService = game:GetService("RunService")

-- constant variables
local CALENDAR = {
	[1] = "January",
	[2] = "February",
	[3] = "March",
	[4] = "April",
	[5] = "May",
	[6] = "June",
	[7] = "July",
	[8] = "August",
	[9] = "September",
	[10] = "October",
	[11] = "November",
	[12] = "December"
}

-- Default timeline
local TimeDate = {
	min = 30,
	hour = 17,
	month = 2,
	day = 17,
	year = 1999,
	sec = 0
}

-- checker variables
local isActivated = false
local isTimeChanging = false

-- change this to how you like time increments
local timeInterval = 1

-- changes lighting of server
local function changeLighting()
	game.Lighting.TimeOfDay = string.format("%s:%s:%s", TimeDate.hour, TimeDate.min, TimeDate.sec)
end

-- returns a string format of a time ie. 02:48 PM
local function transformTime(hour: number, min: number)
	-- transforms num to a hr: min pm format
	local period
	local hour = hour % 24

	if 0 <= hour and hour < 12 then
		period = "AM"
	else
		period = "PM"
		hour = hour - 12
	end

	if hour == 0 then
		hour = 12
	end

	return string.format("%02i: %02i %s", hour, min, period)
end

-- returns a string format of a date ie. February 12, 2013
local function transformDate(month: number, day: number, year: number)
	return string.format("%s %02i, %04i", CALENDAR[month], day, year)
end

-- starts the time clock
local function startTime()
	if isActivated then
		warn("Time already started")
		return
	end
	-- starts timer
	isActivated = true
	task.spawn(function()
		while isActivated do
			task.wait(timeInterval)
			TimeDate.min += 1
			if TimeDate.min == 60 then
				TimeDate.min = 0
				TimeDate.hour += 1
			end
			if TimeDate.hour == 24 then
				TimeDate.hour = 0
				TimeDate.day += 1
			end
			if TimeDate.day == 32 then
				TimeDate.day = 1
				TimeDate.month += 1
			end
			if TimeDate.month == 13 then
				TimeDate.month = 1
				TimeDate.year += 1
			end
			-- updates the lighting
			changeLighting()
			
			-- sends info to all clients about the time stored in server
			-- useful to display time in a players' gui such as text label
			Remotes.SendInfo:FireAllClients("time", transformTime(TimeDate.hour, TimeDate.min))
			Remotes.SendInfo:FireAllClients("date", transformDate(TimeDate.month, TimeDate.day, TimeDate.year))
		end
	end)
end

-- returns the seconds of dateTime with respect to TimeDate
local function getSeconds(dateTime: {})
	local temp = {}
	temp.sec = (dateTime.sec or 0) + TimeDate.sec
	temp.min = ((dateTime.min or 0) + TimeDate.min)
	temp.hour = ((dateTime.hour or 0) + TimeDate.hour)
	temp.day = ((dateTime.day or 0) + TimeDate.day)
	temp.month = ((dateTime.month or 0) + TimeDate.month)
	temp.year = ((dateTime.year or 0) + TimeDate.year)
	return os.time(temp)
end

-- changes the time to fast forward
local function changeTime(newDateTime: {})
	if isTimeChanging then
		warn("Wait for time change to finish")
		return
	end
	isTimeChanging = true
	
	local oldInterval = timeInterval
	local newSecond = getSeconds(newDateTime)
	local newIntervaL = 0.0001
	
	timeInterval = newIntervaL
	
	-- used to continually detect when to stop the time forward
	local hb
	hb = RunService.Heartbeat:Connect(function(deltaTime: number) 
		local temp = getSeconds({})
		if os.difftime(newSecond, temp) > 0 then
			return			
		end
		-- assume that we have reached the end of time forward, so reset to default values
		isTimeChanging = false
		timeInterval = oldInterval
		if hb then
			hb:Disconnect()
		end
	end)
end

-- stops the time... might be useful when playing animations/scenarios that shouldnt affect the clock time
local function stopTime()
	if not isActivated then
		warn("Time already stopped")
		return
	end
	isActivated = false
end

-- tests
-- startTime()
-- task.wait(3)
-- stopTime()
-- task.wait(3)
-- startTime()

3 Likes

What’s the point of this? Couldn’t you just run each function once?

2 Likes

oops forgot to edit that out. i was testing it that’s why