So I want to make a simple login reward system (get a prize every day). So I use os.time() to keep track of how much time elapsed between play sessions. However, I noticed that changing the time on my computer directly effects the value returned by os.time(). On the wiki (Documentation - Roblox Creator Hub) it says to use os.time() instead of tick() for exactly this reason.
Alternatively, I tried using tick(), but noticed that it doesn’t keep track well either and seems also influenced by my systems time (my laptop is old and the clock runs slow, so I noticed this).
I suppose this is a bug because os.time() is supposed to return a universal time stamp (UNIX), but it doesn’t behave that way, for I can change it at will with my own system time. Am I doing anything wrong or overlooking anything?
When running in studio, os.time() will use your system’s time. Typically your server scripts will run on Roblox’s game servers, in which case os.time() should be uniform. On the client, os.time() will not be uniform.
This is not a bug. The os.time function returns the system time of your device, not corrected by the timezone set on your device. If you change your system time, then both tick() and os.time() will be different, the only difference being that one is adjusted by your timezone settings and the other is not.
Between game servers, os.time will be consistent because you may assume that all servers have their system times properly set. For clients, this may not hold, because a client system may not have these settings properly set.
The note on the wiki should be adjusted so that this is more clear, though.
Unix timestamps are not magic. They are just a way of representing the current time of a given device. If you change the device’s current time, then os.time() will return a different value. It does not perform an RPC to the server to get the server time or anything like that. You should probably only call os.time() from the server, in your case, to prevent people from abusing it.
Update (June 2024): You can use Workspace:GetServerTimeNow() to get a time value synchronized between the client and server. However, exploits can still mess with the time values, and you should still check on the server where possible.
Uh, didn’t Roblox do it the other way around from regular Lua? In Roblox, tick() returns the device’s time while os.time() returns UTC by substracting the timezone? If you change your time from (e.g.) 2pm to 3pm and your timezone from GMT to GMT+1, os.time() should return the same value, while tick() now adds an extra hour to its previous value.
Both os.time and tick are affected when you change your time settings. I’m not sure whether that means changing your time settings actually changes the system time that is reported to the Roblox client, or if os.time through Roblox is somehow differently implemented than it is in stock Lua.
I’m pretty sure tick() is what os.time() is in stock Lua, except it has decimals while the vanilla os.time() returned an integer. Later on Roblox added the os library with os.time() which does timezone math.
tick() was supposed to get seconds since the Unix epoch, but just plainly used system time (which was influenced by timezones), so it wasn’t 100% accurate. os.time() “solves” that by substracting the timezone. Of course, if the device’s time doesn’t match the device’s timezone, that won’t work.
That’s correct, os.time() is the unix epoch one and tick() is timezone corrected, both depend on the host os’ system time.
But it probably should to make os.time more consistent, I mean, roblox’s already pretty oppressively always-online so attempting to sync that on startup is probably fine.
I don’t think we currently want to ship an NTP client as part of the client. Ultimately, you can’t trust os.time() anyway, because of client side exploits.