Mercurial > prosody-hg
comparison util/datetime.lua @ 12629:4c1d3f817063
util.datetime: Add support for sub-second precision timestamps
Lua since 5.3 raises a fuss when time functions are handed a number with
a fractional part and the underlying C functions are all based on
integer seconds without support for more precision.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sun, 14 Aug 2022 16:57:31 +0200 |
| parents | e616c37756b3 |
| children | 5d8b0e0b9d48 |
comparison
equal
deleted
inserted
replaced
| 12628:b95da9a593be | 12629:4c1d3f817063 |
|---|---|
| 10 -- XEP-0082: XMPP Date and Time Profiles | 10 -- XEP-0082: XMPP Date and Time Profiles |
| 11 | 11 |
| 12 local os_date = os.date; | 12 local os_date = os.date; |
| 13 local os_time = os.time; | 13 local os_time = os.time; |
| 14 local os_difftime = os.difftime; | 14 local os_difftime = os.difftime; |
| 15 local floor = math.floor; | |
| 15 local tonumber = tonumber; | 16 local tonumber = tonumber; |
| 16 | 17 |
| 17 local _ENV = nil; | 18 local _ENV = nil; |
| 18 -- luacheck: std none | 19 -- luacheck: std none |
| 19 | 20 |
| 20 local function date(t) | 21 local function date(t) |
| 21 return os_date("!%Y-%m-%d", t); | 22 return os_date("!%Y-%m-%d", t and floor(t) or nil); |
| 22 end | 23 end |
| 23 | 24 |
| 24 local function datetime(t) | 25 local function datetime(t) |
| 25 return os_date("!%Y-%m-%dT%H:%M:%SZ", t); | 26 if t == nil or t % 1 == 0 then |
| 27 return os_date("!%Y-%m-%dT%H:%M:%SZ", t); | |
| 28 end | |
| 29 local m = t % 1; | |
| 30 local s = floor(t); | |
| 31 return os_date("!%Y-%m-%dT%H:%M:%S.%%06dZ", s):format(floor(m * 1000000)); | |
| 26 end | 32 end |
| 27 | 33 |
| 28 local function time(t) | 34 local function time(t) |
| 29 return os_date("!%H:%M:%S", t); | 35 if t == nil or t % 1 == 0 then |
| 36 return os_date("!%H:%M:%S", t); | |
| 37 end | |
| 38 local m = t % 1; | |
| 39 local s = floor(t); | |
| 40 return os_date("!%H:%M:%S.%%06d", s):format(floor(m * 1000000)); | |
| 30 end | 41 end |
| 31 | 42 |
| 32 local function legacy(t) | 43 local function legacy(t) |
| 33 return os_date("!%Y%m%dT%H:%M:%S", t); | 44 return os_date("!%Y%m%dT%H:%M:%S", t and floor(t) or nil); |
| 34 end | 45 end |
| 35 | 46 |
| 36 local function parse(s) | 47 local function parse(s) |
| 37 if s then | 48 if s then |
| 38 local year, month, day, hour, min, sec, tzd; | 49 local year, month, day, hour, min, sec, tzd; |
| 39 year, month, day, hour, min, sec, tzd = s:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d)%.?%d*([Z+%-]?.*)$"); | 50 year, month, day, hour, min, sec, tzd = s:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d%.?%d*)([Z+%-]?.*)$"); |
| 40 if year then | 51 if year then |
| 41 local now = os_time(); | 52 local now = os_time(); |
| 42 local time_offset = os_difftime(os_time(os_date("*t", now)), os_time(os_date("!*t", now))); -- to deal with local timezone | 53 local time_offset = os_difftime(os_time(os_date("*t", now)), os_time(os_date("!*t", now))); -- to deal with local timezone |
| 43 local tzd_offset = 0; | 54 local tzd_offset = 0; |
| 44 if tzd ~= "" and tzd ~= "Z" then | 55 if tzd ~= "" and tzd ~= "Z" then |
| 47 if #m ~= 2 then m = "0"; end | 58 if #m ~= 2 then m = "0"; end |
| 48 h, m = tonumber(h), tonumber(m); | 59 h, m = tonumber(h), tonumber(m); |
| 49 tzd_offset = h * 60 * 60 + m * 60; | 60 tzd_offset = h * 60 * 60 + m * 60; |
| 50 if sign == "-" then tzd_offset = -tzd_offset; end | 61 if sign == "-" then tzd_offset = -tzd_offset; end |
| 51 end | 62 end |
| 52 sec = (sec + time_offset) - tzd_offset; | 63 local prec = sec%1; |
| 53 return os_time({year=year, month=month, day=day, hour=hour, min=min, sec=sec, isdst=false}); | 64 sec = floor(sec + time_offset) - tzd_offset; |
| 65 return os_time({year=year, month=month, day=day, hour=hour, min=min, sec=sec, isdst=false})+prec; | |
| 54 end | 66 end |
| 55 end | 67 end |
| 56 end | 68 end |
| 57 | 69 |
| 58 return { | 70 return { |
