16

An API returns a timestamp as UNIX timestamp at UTC and I would like to know if this timestamp was more than x seconds ago. As expected, this works fine with os.time() - x > timestamp in UTC, but blows up in other timezones.

Unfortunately I can't find a good way solve this in lua.

os.date helpfully has the ! prefix (e.g. os.date("!%H:%M:%S")) to return time at UTC, but it seems that despite the documentation stating it supports all strftime options, this does not support the %s option. I have heard people mention that this is caused by Lua compile time options for a similar issue, but changing these is not possible as the interpreter is provided by the user.

Azsgy
  • 3,139
  • 2
  • 29
  • 40

3 Answers3

18

You can use

os.time(os.date("!*t"))

to get the current UNIX epoch.

Joe
  • 41,484
  • 20
  • 104
  • 125
  • ohh that makes a lot of sense. I had tried it the other way around and I couldn't get it to do anything useful! – Azsgy May 08 '17 at 21:48
  • 3
    a note on performance: This is around 500x slower than taking os.time() and subtracting the difference. However because I anticipate bugs with that approach and expect max msg/sec to be around 200 I will go with this. – Azsgy May 08 '17 at 22:21
  • Glad you measured. – Joe May 08 '17 at 23:50
  • 4
    Actually, it fails on my system. linux `date` returns 14:40, `date -u` returns 12:40, but lua `os.time(os.date("!*t"))` returns 1562240400 which corresponds to 13:40, so it seems there are timezone/DST issues – galinette Jul 04 '19 at 12:46
  • 1
    `os.time(os.date("*t"))` works without DST issue – redfast00 Nov 16 '21 at 19:01
6

Ok, so you want the UTC time. Keep in mind that os.time actually knows nothing about timezones, so for example:

os.time(os.date("!*t"))
  1. Will get UTC time and populate table struct.
  2. Will convert table struct according to current timezone to unix timestamp.

So you actually would get your UNIX_TIME - TIMEZONE_OFFSET. If you are in GMT+5 you will get timestamp at UTC-5.

The correct way to do time conversion in lua is:

os.time() -- get current epoch value
os.time{ ... } -- get epoch value for local date/time values
os.date("*t"),os.date("%format") -- get your local date/time
os.date("!*t") or os.date("!%format") -- get UTC date/time
os.date("*t", timestamp),os.date("%format", timestamp) -- get your local date/time for given timestamp
os.date("!*t", timestamp) or os.date("!%format", timestamp) -- get UTC date/time for given timestamp

Kudos to Mons at https://gist.github.com/ichramm/5674287.

If you really need to convert any UTC date to timestamp, there's a good description on how to do this in this question: Convert a string date to a timestamp

kworr
  • 3,579
  • 1
  • 21
  • 33
0

os.time() gives you the unix timestamp. The timestamp is seconds since 00:00:00 UTC on 1 January 1970, so it's the same across timezones.

For example, run this code:

print('timestamp', os.time())
print('local hour', os.date("*t").hour)
print('utc hour', os.date("!*t").hour)

Presumably, your local and utc hour are different. Also run it in an online repl. The server's local and utc hour are the same, but both your and the server's timestamp are about the same.

idbrii
  • 10,975
  • 5
  • 66
  • 107