Need Accurate Time() Value in Seconds

Continuing the discussion from The Ultimate os, time, and tick Tutorial!:

જ⁀➴
According to this post, the time() function should return a value that reads the amount of time, in seconds, passed since the player has joined the game. On the contrary, in my test runs, time() has returned values from hundreds to thousands in a few seconds. In addition, the pace in which the value increases becomes faster too.

I was creating a datastore for my players, storing the total playtime between sessions. The variable, rawTime, is temporary for this instance, supposed to portray the amount of seconds in my test run. The value of playerData[playerKey].playTimeValue is 0. Further coding will calculate the playtime in hours. At this moment, I need an accurate tell of time in seconds so I can ensure accuracy in my datastore values.

local function calcPlayTime(playerKey)
	-- var - saved total playtime + recent sessiontime
	local rawTime = playerData[playerKey].playTimeValue + time()
	return rawTime
	
end

game:GetService("RunService").Heartbeat:Connect(function()
	
	for _, plr in pairs(players:GetPlayers()) do
		local playerKey = ("Player_"..plr.UserId)
		
		if playerData[playerKey] then
			local rawTime = calcPlayTime(playerKey)
			print(rawTime)
			local leaderstats = plr:FindFirstChild("leaderstats")

			if leaderstats and leaderstats:FindFirstChild("Playtime") then
				leaderstats["Playtime"].Value = rawTime
				playerData[playerKey].playTimeValue = rawTime
				
			end	
		end

	end
	
end)
Full Script
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

local playerData = {}

local function addLeaderstats(plr, playerKey)
	
	local leaderstats = Instance.new("Folder", plr)
	leaderstats.Name = "leaderstats"

	local playTime = Instance.new("NumberValue", leaderstats)
	playTime.Name = "Playtime"
	playTime.Value = playerData[playerKey].playTimeValue
	print(playerKey, "played", playTime.Value)

end

game.Players.PlayerAdded:Connect(function(plr)
	
	local playerKey = ("Player_"..plr.UserId)
	local success, sessionData;
	local count = 0

	repeat
		
		success, sessionData = pcall(function()
			return playerDataStore:GetAsync(playerKey)
		end)
		
		if not success then
			count += 1
			warn("Fetching data, attempt #"..count, "\nError:", sessionData)
			task.wait(5)
		end
		
	until success or count >= 12
	
	if success then
		
		print("success", sessionData)
		
		if not sessionData then
			sessionData = {
				playTimeValue = 0;
			}
		end
		
		playerData[playerKey] = sessionData
		print(playerData[playerKey])
		
	else
		
		warn("Unable to fetch data for:", playerKey)
		plr:Kick("Unable to fetch your data, rejoin or try again later. >:(")
		
	end
	
	addLeaderstats(plr, playerKey)
	
end)

game.Players.PlayerRemoving:Connect(function(plr)
	
	local playerKey = ("Player_"..plr.UserId)
	
	if playerData[playerKey] then
		local success, err;
		local count = 0
		
		repeat
			
			success, err = pcall(function()
				playerDataStore:UpdateAsync(playerKey, playerData[playerKey])
			end)

			if not success then
				count += 1
				warn("Saving data, attempt #".. count, "\nError:", err)
				task.wait(5)
			end

		until success or count >= 12
		
		if success then
			print("Data saved for", playerKey)
		else
			warn("Data unsaved for", playerKey)
		end
		
	end
	
end)

local function calcPlayTime(playerKey)
		
	local rawTime = playerData[playerKey].playTimeValue + time()
	return rawTime
	
end

game:GetService("RunService").Heartbeat:Connect(function()
	
	for _, plr in pairs(players:GetPlayers()) do
		local playerKey = ("Player_"..plr.UserId)
		
		if playerData[playerKey] then
			local rawTime = calcPlayTime(playerKey)
			print(rawTime)
			local leaderstats = plr:FindFirstChild("leaderstats")

			if leaderstats and leaderstats:FindFirstChild("Playtime") then
				leaderstats["Playtime"].Value = rawTime
				playerData[playerKey].playTimeValue = rawTime

			end	
		end

	end
	
end)

જ⁀➴
The following attachments present the output when print(rawTime) is running. In the screenshot, the difference between print(time()) and print(rawTime) is noticeably different; as a result, my goal is for the result of print(rawTime) to accurately represent the result print(time()).

output

Test Run - Video

౨ৎ
With appreciation,
vamp

3 Likes

That is only true in local scripts. Otherwise, it gives the time (in seconds) since the server started.


The reason the value goes up so rapidly is because of the calcPlayTime function, because you are adding the total amount of time each time it fires (which happens to be every single heartbeat).
In order for it to work the way I believe you intended, you would need to be adding DeltaTime, instead of time().

DeltaTime can be obtained from the first parameter of the HeartBeat function
(i.e. .HeartBeat:Connect(function(DeltaTime)

2 Likes

You could use timestamps, instead of a discrete tick system.

Basically, you log the timestamp of which a player joined, and the timestamp of which they would then leave.

Use those 2 timestamps you’ve gotten to calculate how long the player has stayed in game, and then save it into your datastores.

@SeargentAUS,

Yes, that makes sense. I will try the DeltaTime Variable and report back.

I was hoping to assign rawTime with an unrounded value to store under the player for accuracy inbetween sessions, and an additional variable to round to the nearest 0.1 of an hour on leaderstats. That is why rawTime exists.

@Solar_Eos,

That is true, and seems to work efficiently in other scripts. The following post was my guide:

How can I log and save time spent ingame properly?

Learning of time(), I figured that method was more of a hassle. I will definitely try that if all goes wrong, lol.

Thank you to both for your help.

For any future reference, the following script calculates the total playtime efficiently. In case of any retries to save data and the RunService continues, deltaTime keeps it tidy.

જ⁀➴

local function calcPlayTime(playerKey, deltaTime)

	local rawTime = playerData[playerKey].playTimeValue + deltaTime
	local roundTime = rawTime --any arithmetic to convert into minutes, hours, etc.

	return rawTime, roundTime

end

game:GetService("RunService").Heartbeat:Connect(function(deltaTime)

	for _, plr in pairs(players:GetPlayers()) do
		local playerKey = ("Player_"..plr.UserId)

		if playerData[playerKey] then

			local rawTime, roundTime = calcPlayTime(playerKey, deltaTime)
			print(rawTime, roundTime)

			local leaderstats = plr:FindFirstChild("leaderstats")

			if leaderstats and leaderstats:FindFirstChild("Playtime") then
				leaderstats["Playtime"].Value = roundTime
				playerData[playerKey].playTimeValue = rawTime
				-- set their time played to what was saved + how long it's been since they've joined (in min)
			end	
		end

	end

end)

Appreciated,
vamp

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.