Os.date displays time wrong

I use os.date() to show the unban time in my moderation system. The format string is *t, and it should show my local time, but it doesn’t. If it’s 13:27:00 for me, it shows that time in studio, but in-game it shows 11:27:00. I have tried anything i know of and it doesn’t work. What am I doing wrong.

The code is inside a function in a module script called BanLengthHandler.

Code: (Sorry if it’s a bit messy)

        --The if statements are for showing ex. 2022-06-23 instead of 2022-6-23.
       -- Look at the returns.
       -- I know that there is probably better ways to do this, but this is what i did.
	local TimeFinished = StartTime + BanLength -- Unix unban time
	
	local unbanDate = os.date("*t", TimeFinished) -- The date for the unban
	
	if unbanDate["month"] > 9 and unbanDate["day"] > 9 then
		return("" .. unbanDate["year"] .. "/" .. unbanDate["month"] .. "/" .. unbanDate["day"] .. " " .. unbanDate["hour"] .. ":" .. unbanDate["min"] .. ":" ..unbanDate["sec"])
	elseif unbanDate["month"] < 9 and unbanDate["day"] <9 then
		return("" .. unbanDate["year"] .. "/0" .. unbanDate["month"] .. "/0" .. unbanDate["day"] .. " " .. unbanDate["hour"] .. ":" .. unbanDate["min"] .. ":" ..unbanDate["sec"])
	elseif unbanDate["month"] < 9 and unbanDate["day"] > 9 then
		return("" .. unbanDate["year"] .. "/0" .. unbanDate["month"] .. "/" .. unbanDate["day"] .. " " .. unbanDate["hour"] .. ":" .. unbanDate["min"] .. ":" ..unbanDate["sec"])
	elseif unbanDate["month"] > 9 and unbanDate["day"] < 9 then
		return("" .. unbanDate["year"] .. "/" .. unbanDate["month"] .. "/0" .. unbanDate["day"] .. " " .. unbanDate["hour"] .. ":" .. unbanDate["min"] .. ":" ..unbanDate["sec"])	
	end
end
1 Like

I think you could simplify your string slightly using Formatting and Converting Strings (roblox.com).

I believe the time differences is due to Studio using your local computer time, but the servers using another timezone. As os (roblox.com) states, I believe the servers are using UTC as time zone, while you seem to be in UTC +2.

This happens because you use os.date on the server, therefore it retrieves the date based on the Roblox server timezone. Instead to get your local time, you must use os.date in a local script. The reason this doesn’t happen in studio is because when testing, your own computer is the fake server running the simulation.

1 Like

The string formatting I use seem to work, but I can change it later if I have time.

How do I do this? The ban length handler is a module script, and I guess that I can’t call a function from a module with a local script. Also, I have to read data from a ban datastore, and that can’t be done with a localscript as far as I know. @PAGOTATZIS2

I don’t fully agree with @PAGOTATZIS2, the server will always give you the time in UTC+0 which is good for handling the actual ban since it will be consistent.

Do you want to display what time the ban will be lifted using the clients current time zone? In that case I would use a remote function to ask the server for time of ban-lift as well as the current time on the server.

By getting the current server time and calling os.time() on the client you will be able to get the difference. Divide by 3600 and round the difference and you will get the hour difference. Add this value to the received ban-lift time and you are done.

local banExpirationTime, serverTime = remoteFunction:InvokeServer()

local utcZone = math.round((serverTime - os.time()) / 3600)
-- utcZone will give you which UTC they are in. (UTC+1 / UTC-3 etc.)

Or… client altered PC’s time but server is not.

Sorry? I don’t understand what you mean. If a client alters their PC time then they will just get the wrong info displayed to them, but that is on them at that point. The actual ban duration will stay the same as it is based on the server.

1 Like

Thank you. I use os.time (Unix) to handle the actual bans, and then i convert the unix to a date to show to the user. The Unix time is not different on the client and server, I think. In my ban datastore, I have the os.time (Unix) of when the user was banned, and then I store the duration of the ban (in seconds) ex. 1 day = 86400 seconds. I calculate the unban unix time in a module script:

local BanUnixTime = Data[3] -- The ban time in the data table
local BanDuration = Data[4] -- The ban duration time in the data table

local UnbanTime = BanUnixTime + BanDuration

if os.time() >= UnbanTime then
    return "Unbanned"
end

I will try to use your example. But I am a bit unsure on how to display the ban time in the kick message, as the kick is handled in a Module script. Is there any easy way to do it. Also, if you have any more things to add, please tell me. I am also scratching my head a bit because i’m using the formatstring “*t” in os.date, and that should return the local time (Am I wrong)? I would appreciate more help.

You could store all time zones of players. When they join they can send their current time through a remote event, store the difference in hours in a table and then when they get kicked you apply said difference in the message.

I could do that, thank you. Are the timezones going to be saved using a datastore?

I don’t think that is necessary, you don’t need the time zones except for displaying the information to the user, which they will provide whenever they join.

Ok, thank you for all the help.

No problem, if you require anymore help just ping me or reply to this comment. Don’t forget to mark this post as solved once you deem it solved.

Seems best just to go with the server time when compiled and just not show the actual time in game.
Datetime Date/Time-format-strings from Roblox gives you all you could ask for, for testing/setting whatever time.

It is of course easier to not account for their time zone, but in this case the issue was to display the time in the correct time zone.

If you use the things from the link, and put in there player’s localization ex. “se-swe” (I don’t know what the Swedish locale is named) would it show the time in the correct time zone?

You actually have all that with a little math. I also like how you can zero in on any time variation with it.

1 Like

Yes, my bad when it came to that one. I misread it as the link for os.date() rather than the link it actually was, so I didn’t bother looking at it.

Looks to me as you can see in that link there that is for the languages used for sure … other than that I’d have to do a few test to be sure. Getting the right time zone from there would just be a matter of figuring out the amount of time each zone differs from the one you’re getting. os can do that …

local a = os.date("!*t") --> this universal time (server time) 
print(a.hour) 

local b = os.date("*t") --> this is you in your time zone
print(b.hour) 

local dif = os.difftime(a.hour, b.hour)
print(dif)

I know super sloppy, but within them the math is there to figure time zone differences.

You could just forget all about time zones and tell them how long they have left on the ban.
[ Your ban expires in 3 hours 37 min ]