The left is Roblox Studio, the right is Roblox In-game
Here is my script
wait()
local MF = math.floor
local Next = next
local Tick = tick
local Wait = wait
local Stop = 0
local Timer = -1
while true do Wait(Timer)
wait()
local Time = 1634891429 - Tick()
local Days = MF((Time / 60 / 60 / 30) % (250 + 0.250))
local Hours = MF((Time / 60 / 60) % 30)
local Minutes = MF((Time / 60) % 60)
local Seconds = MF(Time % 60)
if Stop == 0 then
script.Parent.Time.Text = Days..":"..Hours.. ":"..Minutes..":"..Seconds.." "
end
if Days==0 and Hours==0 and Minutes==0 and Seconds==0 or Time < 0 then
Stop=0
script.Parent.Time.Text = "Rejoin!"
end
end
Roblox Studio runs on your local machine in a local server on your machine. Therefore, it uses your timezone.
Roblox Player connects you to a server that could be located technically anywhere, but it’s typically close to you. That means the timezone of the server could be different than yours.
Studio uses your local time zone. Actual servers do not. I personally use DateTime.now().UnixTimestampMillis to ensure it’s the same across all servers and you could probably do time zone conversions in a local script (but that doesn’t matter for a countdown as that’s relative and not absolute).
i.e. if you want to count until a specific unix timestamp, you can use https://www.unixtimestamp.com/ this to enter the time you want your count down to end (in your time zone), copy the value in the table after “Unix Timestamp.” This value does not include milliseconds, if that doesn’t matter to you, you can instead use DateTime.now().UnixTimestamp, but it matters to me so I multiply the value by 1000 (just add 3 zeroes to the end), you can use these 3 places as very precise to the millisecond count downs. Once you have the value you want (I will be using 1635170400000 as an example, which is 10/25/2021 10 AM EDT, or 2 PM GMT+0) you can do something along these lines:
(This is very simplified)
local endTime = 1635170400000
while true do
local now = DateTime.now().UnixTimestampMillis -- We do this to prevent creating many date objects unnecessarily.
if now > endTime then break end -- count down is over
-- Otherwise in here you can update the timer
-- How you do this really doesn't matter, but you can do (endTime - now)
-- to get the time remaining, in milliseconds then format that however you want.
task.wait(0.02)
end
You can also avoid creating any additional datetime objects if you really wanted:
local endTime = 1635170400000
local now = DateTime.now().UnixTimestampMillis
while true do
now += task.wait(0.02)*1000 -- task.wait returns the time waited in seconds, multiply by 1000 for milliseconds.
if now >= endTime then break end
-- ... (endTime - now) to get time remaining in milliseconds
end
Avoiding the date object creation is more efficient on memory. But both work.