Files
491cda1a58 feat(plugins/datetime): Add local/UTC conversion (#7122)
I mentioned in #7096 that it's helpful to convert between UTC and local
timezones. This PR adds methods for this.


Co-authored-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
Parent-pr: https://github.com/Chatterino/chatterino2/pull/7096
2026-08-05 18:47:31 +00:00

133 lines
4.4 KiB
Lua

---@generic T
---@param a T
---@param b T
local function assert_eq(a, b)
if a ~= b then
error(tostring(a) .. " ~= " .. tostring(b))
end
end
local specs_ms = {
{
iso_ms = "2026-07-10T20:14:41.477Z",
iso_sec = "2026-07-10T20:14:41Z",
unix_ms = 1783714481477,
unix_sec = 1783714481,
},
{
iso_ms = "1930-11-18T00:28:29.123Z",
iso_sec = "1930-11-18T00:28:29Z",
unix_ms = -1234567890877,
unix_sec = -1234567890,
},
}
local specs_sec = {
{
iso_ms = "2026-07-10T20:14:41.000Z",
iso_sec = "2026-07-10T20:14:41Z",
unix_ms = 1783714481000,
unix_sec = 1783714481,
},
{
iso_ms = "1930-11-18T00:28:29.000Z",
iso_sec = "1930-11-18T00:28:29Z",
unix_ms = -1234567891000,
unix_sec = -1234567891,
},
}
local tests = {
iso_string_invalid = function()
local dt = c2.DateTime.from_iso_string("invalid")
assert_eq(dt:to_unix_milliseconds(), 0)
assert_eq(dt:to_iso_string(), "")
end,
iso_string_ms = function()
for _, spec in pairs(specs_ms) do
local dt = c2.DateTime.from_iso_string(spec.iso_ms)
assert_eq(dt, c2.DateTime.from_iso_string(spec.iso_ms))
assert_eq(dt:to_iso_string(), tostring(dt))
assert_eq(dt:to_iso_string(), spec.iso_ms)
assert_eq(dt:to_iso_string_without_ms(), spec.iso_sec)
assert_eq(dt:to_unix_milliseconds(), spec.unix_ms)
assert_eq(dt:to_unix_seconds(), spec.unix_sec)
assert(dt:is_utc())
end
end,
iso_string_sec = function()
for _, spec in pairs(specs_sec) do
local dt = c2.DateTime.from_iso_string(spec.iso_sec)
assert_eq(dt, c2.DateTime.from_iso_string(spec.iso_ms))
assert_eq(dt, c2.DateTime.from_iso_string(spec.iso_sec))
assert_eq(dt:to_iso_string(), tostring(dt))
assert_eq(dt:to_iso_string(), spec.iso_ms)
assert_eq(dt:to_iso_string_without_ms(), spec.iso_sec)
assert_eq(dt:to_unix_milliseconds(), spec.unix_ms)
assert_eq(dt:to_unix_seconds(), spec.unix_sec)
assert(dt:is_utc())
end
end,
current_time = function()
local dt = c2.DateTime.current_local()
-- We don't know what it should be, but we know that it must be valid.
assert(dt:to_iso_string() ~= "")
assert(dt:is_local())
dt = c2.DateTime.current_utc()
assert(dt:to_iso_string() ~= "")
assert(dt:is_utc())
end,
unix_timestamp_ms = function()
for _, spec in pairs(specs_ms) do
local dt = c2.DateTime.from_unix_milliseconds(spec.unix_ms)
assert_eq(dt, c2.DateTime.from_unix_milliseconds(spec.unix_ms))
assert_eq(dt:to_unix_milliseconds(), spec.unix_ms)
assert_eq(dt:to_unix_seconds(), spec.unix_sec)
assert(dt:is_local())
assert_eq(dt, c2.DateTime.from_iso_string(spec.iso_ms))
assert_eq(dt:to_utc():to_iso_string(), spec.iso_ms)
assert_eq(dt:to_utc():to_iso_string_without_ms(), spec.iso_sec)
end
end,
unix_timestamp_sec = function()
for _, spec in pairs(specs_sec) do
-- without milliseconds
local dt = c2.DateTime.from_unix_seconds(spec.unix_sec)
assert_eq(dt, c2.DateTime.from_unix_seconds(spec.unix_sec))
assert_eq(dt, c2.DateTime.from_unix_milliseconds(spec.unix_ms))
assert_eq(dt:to_unix_milliseconds(), spec.unix_ms)
assert_eq(dt:to_unix_seconds(), spec.unix_sec)
assert(dt:is_local())
assert_eq(dt, c2.DateTime.from_iso_string(spec.iso_ms))
assert_eq(dt:to_utc():to_iso_string(), spec.iso_ms)
assert_eq(dt:to_utc():to_iso_string_without_ms(), spec.iso_sec)
end
end,
local_utc_conversion = function()
local dt_utc = c2.DateTime.current_utc()
local dt_local = dt_utc:to_local()
assert(dt_utc:is_utc())
assert(dt_local:is_local())
assert_eq(dt_local, dt_utc)
dt_local = c2.DateTime.current_local()
dt_utc = dt_local:to_utc()
assert(dt_utc:is_utc())
assert(dt_local:is_local())
assert_eq(dt_local, dt_utc)
end,
}
for name, fn in pairs(tests) do
local ok, res = xpcall(fn, debug.traceback)
if not ok then
error(name .. " failed: " .. res)
end
end