Time System..... that cycles

Hello, I have fabricated a script that will most likely be the core time for my game. I’m posting it here and asking for feedback because I feel I’m probably doing something slightly wrong. Also just because i’m tired of working on this. I would really appreciate any insight on making it as accurate as possible.

To sumarize the code, it pretty much does all the calculations from a static date to determine the in game time. It calculates in game minutes and days through the current day and months/weeks from a specific date. It then uses runservice.stepped to constantly update these dates; Each in game minute is equal to 2 seconds.

This code is obviously far from complete, but I would really appreciate some feedback on the whole time mechanic since that’s what I’m most concerned about (this is also my first time actually trying to mess with os). I plan on using datastores to store the time each time the ‘cycle’ rolls over. Will probably also add some checking if the time in the datastore is exceeding 12 days.

Sorry if what I wrote doesn’t make sense, I wanted to post this before I went to sleep and I can barely write cohesively. As a side note, I also just added the checking in runservice.stepped() so it probably doesn’t work as intended.

Actually this is important, I know for a fact that it doesn’t change the weekDay properly so any simple code without using an if statement would be much appreciated.

--VARIABLES
local replicatedStorage = game.ReplicatedStorage
local sharedData = replicatedStorage.SharedData
local dayVariable = sharedData.MonthDay
local weekDayVariable = sharedData.WeekDay
local monthVariable = sharedData.Month
local seasonVariable = sharedData.Season
local minutesVariable = sharedData.Minutes

local runService = game:GetService("RunService")

local dateModule = require(replicatedStorage.ModuleScripts.DateData)

--GETS TIME
local baseTime = os.time({year = 2022, month = 7, day = 1, hour = 0, min = 0, sec = 0})
local utcTime = os.date("!*t")
local oldWeekday = 1

--TIME FUNCTIONS
--Minutes--
local function changeMinutes(currentTime)
	local seconds = (((currentTime["hour"]) * 60) * 60) + (currentTime["min"] * 60) + (currentTime["sec"])
	local gameMinutes = math.round((seconds % 2880) / 2)
	print(gameMinutes)
	return gameMinutes
end

--Day--
local function changeDay(currentTime)
	local minutes = ((currentTime["hour"]) * 60) + currentTime["min"]
	local gameMonthDay = math.floor(minutes / 48) + 1
	return gameMonthDay
end

--Weekday--
local function changeWeekDay(currentCycle)
	local diffTime = os.difftime(os.time(), currentCycle)
	local days = math.floor(diffTime/60/60/24)
	local weekDay = oldWeekday + days
	if weekDay > 7 then weekDay -= 7 end
	return weekDay
end

--Month--
local function changeMonth(currentCycle)
	local diffTime = os.difftime(os.time(), currentCycle)
	local month = math.floor(diffTime/60/60/24)
	return month
end

--Season--
local function changeSeason(currentMonth)
	local seasonMonth = dateModule["SeasonMonths"][(dateModule["MonthNames"][currentMonth])]
	return seasonMonth
end

--CHANGES TIME
minutesVariable.Value = changeMinutes(utcTime)
dayVariable.Value = changeDay(utcTime)
monthVariable.Value = dateModule["MonthNames"][changeMonth(baseTime)]
seasonVariable.Value = changeSeason(changeMonth(baseTime))
weekDayVariable.Value = dateModule["WeekNames"][changeWeekDay(baseTime)]

--UPDATES TIME
local oldSeconds = utcTime["sec"]
local oldDay = utcTime["day"]

--Stepped--
local debounce = false
runService.Stepped:Connect(function()
	local currentTime = os.date("!*t")
	local currentSeconds = (((currentTime["hour"]) * 60) * 60) + (currentTime["min"] * 60) + (currentTime["sec"])

	--Changes Game Minutes--
	if currentSeconds > oldSeconds + 1 then
		if debounce == true then return end
		debounce = true

		minutesVariable.Value = changeMinutes(currentTime)
		oldSeconds = currentSeconds

		--Changes Game Day--
		if currentSeconds % 2880 == 0 or currentSeconds > oldSeconds + 2880 then
			changeDay(currentTime)
			changeWeekDay(oldWeekday)
		end

		--Changes Game Month--
		if currentTime["day"] ~= oldDay then
			--Makes Sure Base Time Hasn't Exceeded 12 Days--
			if baseTime/60/60/24 > 12 then
				baseTime = os.time({year = currentTime["year"], month = currentTime["month"], day = currentTime["day"], hour = 0, min = 0, sec = 0})
				oldWeekday = weekDayVariable.Value
			end

			monthVariable.Value = changeMonth(baseTime)
			seasonVariable.Value = changeSeason(baseTime)
		end

		debounce = false
	end
end)

TimeShare.rbxl (30.2 KB)

1 Like

Set days more than monthes… it looks like both are pointing same

Ok so unless I got it wrong, you’re doing something absolutely overcomplicated for no reason. In order to interact with date and time, most computer systems use a representation of time called “timestamp”. A timestamp is basically a number that represents how much time (in seconds or in milliseconds, up to you) elapsed since a given fixed point in time, called Epoch. The most commonly used Epoch is the Unix Epoch, defined to be January 1st, 1970. However, you may define your own Epoch for your own purpose.

When using the tick() function, Luau will give the current Unix timestamp in seconds, yet with decimal precision. If you were looking for an integer timestamp, you’d use math.floor(tick()). If you wanted a millisecond timestamp, you’d do math.floor(tick() * 1000).

Now obviously, since you’re trying to make custom time, you won’t use tick(), but you can still use a timestamp. Why is it more convenient?

  • You will carry one single value that contains all the information you need, instead of multiple
  • You may retrieve the time from a timestamp under any format you like using os.date, but for instance doing it on the client
  • It’s a lot easier to work with when it comes to comparing dates (can compare timestamps as simple numbers), adding and substracting dates or durations (simple number additions and subtractions)

Final point, how to compute your custom time?
If the mattermost is time precision in regard to your Epoch, then the safe option is to regularly recompute the current custom time based on the real current time, e.g. custom = (realTime - customEpoch + realEpoch) * customTimeSpeed. This, however, doesn’t need to be networked.
Otherwise, a simple loop regularly incrementing your custom timestamp located in a single value will do a great job.

2 Likes

Yeah, I was doing this at first but then I thought it would be easier math-wise to just keep changing the date (especially since I was confused). I have a better understanding of it now, so I should be able to change it without much error. Thank you.

I just quickly added this to the code and ended up making the same mistake, but I understand how to do it now.

I reckon this would be a lot simpler if you used the built in DateTime objects. DateTime | Roblox Creator Documentation