Linux – How to make awesomewm textclock reflect timezone change

arch linuxawesomeclocktimezone

I am using the awful.widget.textclock widget to display the time in Awesome WM on Arch Linux, and I am using a program called tzupdate to automatically update my system time according to geolocation periodically.

I travel frequently, so I thought it would be nice to automate this. However, the textclock widget does not change the time unless I restart Awesome (or relog/restart). Is there something I could add in the lua script to make the widget refresh the timezone?

tzupdate is working fine. I have it on a systemd timer that updates the timezone every five minutes. The system's timezone is successfully changed in this way. The output of timedatectl immediately shows the updated timezone, and the output of the date command correctly displays the correct updated local time.

However, as noted above, Awesome fails to notice this timezone change until I restart (CtrlModR) or logout.

Best Answer

Below is an updated textclock.lua widget that responds to timezone changes at runtime. I replaced the file /usr/share/awesome/lib/awful/widget/textclock.lua. I also installed the luatz module from this github repo and moved the luatz folder to /usr/share/lua/5.2/luatz so that the lua require function finds it automatically.

/usr/share/awesome/lib/awful/widget/textclock.lua:

local setmetatable = setmetatable
local os = os
local textbox = require("wibox.widget.textbox")
local capi = { timer = timer }
local luatz = require("luatz")
local tzcache = require("luatz.tzcache")

--- Text clock widget.
-- awful.widget.textclock
local textclock = { mt = {} }

--- Create a textclock widget. It draws the time it is in a textbox.
-- @param format The time format. Default is " %a %b %d, %H:%M ".
-- @param timeout How often update the time. Default is 60.
-- @return A textbox widget.
function textclock.new(format, timeout)
    local format = format or " %a %b %d, %H:%M "
    local timeout = timeout or 60

    local w = textbox()
    local timer = capi.timer { timeout = timeout }
    timer:connect_signal("timeout", function() 
        tzcache.clear_tz_cache()
        w:set_markup(os.date("!"..format, luatz.time_in())) 
    end)
    timer:start()
    timer:emit_signal("timeout")
    return w
end

function textclock.mt:__call(...)
    return textclock.new(...)
end

return setmetatable(textclock, textclock.mt)
Related Question