Is there any way to "tween" TimeOfDay?

I am making a smooth lighting transition system, mainly using TweenService, but I came to a stop when I realized that I don’t know how I would smoothly transition TimeOfDay to a set value.
This obviously most likely can’t be done very well with TweenService, but is there any way to accomplish this?

1 Like

You can use the ClockTime Property, since it’s a number that can be manipulated using TweenService, though I haven’t tried using it myself.

Example:

15:30:00 == 15.5 (ClockTime)
8 Likes

is there a formula I can use to convert TimeOfDay to clocktime?
for example if I make a string ‘10:11:12’, how would I convert that?

You can do:

local timeofday = "10:11:12"
local function translateClockTime(str)
    return tonumber(str:sub(1,2)) + tonumber(str:sub(4,5))/60 + tonumber(str:sub(7,8))/3600
end

-- test
print(translateClockTime(timeofday))


--> Output:  10.186666666667
1 Like

Just get the ClockTime and that’s the conversion.

local clockTime = game.Lighting.ClockTime
6 Likes
local function TOD_to_CT(str)
	local a = str:split(':')
	local hr,m,s = a[1],a[2],a[3]
	hr,m = hr*3600,m*60
	local CT = hr+m+s
	return (CT/60)/60
end

print(TOD_to_CT('10:11:48'))

Wrote a simple converter for you, to tween from the time you want specifically, just do something like this,

local TS = game:GetService('TweenService')
local Lighting = game:GetService('Lighting')

local function string_to_clock(str)
	local a = str:split(':')
	local hr,m,s = a[1],a[2],a[3]
	hr,m = hr*3600,m*60
	local CT = hr+m+s
	return (CT/60)/60
end

local function tweenTime(targettime,duration)
	local goal = {}
	goal.ClockTime = string_to_clock(targettime)
	local tinfo = TweenInfo.new(duration)
	local tween = TS:Create(game.Lighting,tinfo,goal)
	tween:Play()
end

Lighting.TimeOfDay = '07:00:00' -- Sets your time to 7am

tweenTime('00:00:00',10) -- Tweens to midnight in 10 seconds
3 Likes

Ideally you should never have to use TimeOfDay anymore. That’s why they added ClockTime. It simplifies the whole process and lets you animate the time much easier.

2 Likes

Try heartbeat!

RunService.Heartbeat:Connect(function(delta)
	Lighting.ClockTime = Lighting.ClockTime + delta
end)

I fixed it from the previous answer, @ScriptingSupport.

Heartbeat isn’t tweening though, you’re just counting on the signal to fire to serve as the interval for a while loop. Not really something you should be doing when you can hook the ClockTime set straight to Heartbeat and use the provided delta as an offset. Heartbeat-based waits would also be acceptable, but not a raw wait for the signal.

I’m aware it isn’t tweening, but shouldn’t it create a very smooth look?

I think the biggest issue, is ClockTime is not replicated on the client. It says it here:
https://developer.roblox.com/en-us/api-reference/property/Lighting/ClockTime

I would also argue that you shouldn’t be tweening server-side though. Just have the server fire a RemoteEvent to tell the clients what time they should tween to & then do it on the client. It will be a much smoother user experience.

Yeah, I misread the how the ClockTime variable is replicated. I put originally that it is only replicated on the client and edited quickly after but I’ve come to the realization that makes much less sense.

1 Like

You can do something similar to the :Lerp() method maybe. Basically a function that will have the same behaviour as lerp, but it would work for numbers (:Lerp() only works for vector3 cframe and color3) as well.

local function lerp(val, target, percentage)
   return val + (target - val) * percentage
end

for i = 0, 1, 0.1 do
   wait(0.1)
   lerp(lightning.ClockTime, 23, i)
end

This is probably how the :Lerp() is written in the roblox api.

You can find more information on what I did here!

Just use clock time.

TimeOfDay strings aren’t a regular grammar and life is too short to make a parser that replicates the quirks of the TOD property setter. +4::-8::::: is a totally valid TimeOfDay string.

Close enough.

local function tweenTimeOfDay(tod0, tod1)
	local n0, d do
		local sign0, h0, m0, s0 = tod0:match('^([+-]?)(%d*):[+-]?(%d*):[+-]?(%d*)$')
		local sign1, h1, m1, s1 = tod1:match('^([+-]?)(%d*):[+-]?(%d*):[+-]?(%d*)$')

		if sign0 and sign1 then
			n0 = 3600*(tonumber(h0) or 0) + 60*(tonumber(m0) or 0) + (tonumber(s0) or 0)
			local n1 = 3600*(tonumber(h1) or 0) + 60*(tonumber(m1) or 0) + (tonumber(s1) or 0)
			if sign0 == '-' then
				n0 = -n0
			end
			d = (43200 + (sign1 ~= '-' and n1 or -n1) - n0)%86400 - 43200
		else
			error('invalid TimeOfDay string', 4)
		end
	end
	return function(t)
		local fs = (n0 + d*t)%86400
		local s = fs > 0 and fs or -fs
		return string.format(
			fs < 0 and '-%.2u:%.2u:%.2u' or '%.2u:%.2u:%.2u',
			(s - s%3600)/3600,
			(s%3600 - s%60)/60,
			s%60
		)
	end
end
tweenTimeOfDay('8:00', '10:00')(0.5) -> '9:00:00'
2 Likes