如何在 lua 中更新时间以反映执行期间的系统时区更改



>问题

我想修改 awesome-wm 中的awful.widget.textclock小部件以立即反映系统时区的变化。 这个小部件和所有很棒的wm配置都是用lua编写的。

目前,如果系统时区发生更改,小部件将继续根据运行时设置的时区显示时间。 小组件使用 os.time 函数检索时间,但这与系统时间不匹配。


解决方案如下

Lua 脚本:

local tz=require"luatz";
require "luatz.tzcache".clear_tz_cache()
print("Before Changes (America/Los_Angeles)")
print(os.date("!%H:%M",tz.time_in()))
os.execute("timedatectl set-timezone America/Chicago")
require "luatz.tzcache".clear_tz_cache()
print("America/Chicago")
print(os.date("!%H:%M",tz.time_in()))
os.execute("timedatectl set-timezone America/New_York")
require "luatz.tzcache".clear_tz_cache()
print("America/New_York")
print(os.date("!%H:%M",tz.time_in()))

输出:

Before Changes (America/Los_Angeles)
15:33
America/Chicago
17:33
America/New_York
18:33

解决方法

可以通过重新启动很棒的窗口管理器来解决,这会导致小部件再次获得正确的时区。 当然,如果时区发生变化,则需要再次重新启动窗口管理器。

所需的效果是在系统更改时从系统更新时区,无论是定期还是每次调用 os.time 函数时。


用例

如果您好奇,可以在笔记本电脑上使用它。 我经常旅行,tzupdatesystemd timer上跑步。 我想自动更改我的时区。 这工作正常,除了实际显示时间的小部件没有注意到系统时区的变化。


到目前为止已尝试

  1. 取消设置"$TZ"环境变量。 但是 Arch Linux 从一开始就没有设置这个变量,所以我不确定 lua 是如何确定正确的时区的。
  2. 使用luatz库,特别是tzcache.clear_tz_cache()函数。 这似乎没有效果。
  3. 使用除 os.time() 以外的函数检索系统时间:luatz.time()luatz.gettime.gettime() 。 这些函数检索与其他函数相同的时间。
  4. 使用 luatz.time_in() 函数,但这将返回时区偏移量应用 UTC 时间两次的时间。 luatz.time()返回正确的本地时间,但应该返回 UTC 时间。

更新luatz

我尝试按照建议弄乱luatz库,但即使在调用tzcache.clear_tz_cache()函数后,它似乎也没有重新检查系统时区。

我克隆了luatz存储库并luatz复制到系统模块目录中。 脚本似乎已正确加载,但尚未更改忽略系统时区更改的效果。 据我所知,这与os.time()函数没有任何不同。

卢阿茨测试脚本:

local luatz = require "luatz"
local tzcache = require "luatz.tzcache"
local gettime = require "luatz.gettime"
print ("nBefore Change - System TZ is ")
os.execute("timedatectl | grep 'Time zone' | awk '{ print $3 }'")
print("nos.time(): "..os.date("%H:%M", os.time()))
print("luatz.time(): "..os.date("%H:%M", luatz.time()))
print("gettime..gettime(): "..os.date("%H:%M", gettime.gettime()))
print("nTime zone changed to America/New_York")
os.execute("timedatectl set-timezone America/New_York")
tzcache.clear_tz_cache()
print ("nAfter  Change - System TZ is ")
os.execute("timedatectl | grep 'Time zone' | awk '{ print $3 }'")
print ("nos.time(): "..os.date("%H:%M", os.time()))
print ("luatz.time(): "..os.date("%H:%M", luatz.time()))
print("gettime.gettime(): "..os.date("%H:%M", gettime.gettime()))

输出:

Before Change - System TZ is 
America/Los_Angeles
os.time(): 11:54
luatz.time(): 11:54
gettime..gettime(): 11:54
Time zone changed to America/New_York
After  Change - System TZ is 
America/New_York
os.time(): 11:54
luatz.time(): 11:54
gettime.gettime(): 11:54

luatz.time_in()

因此,luatz.time_in()功能确实会随着系统时区的变化而更新,我对此感到兴奋! 但是,time_in() 不会显示正确的本地时间。 它将时区偏移量添加到正确的本地时间,导致时间落后几个小时。 我尝试设置TZ环境变量,但这没有效果。 出于某种原因,luatz.time()返回本地时间,luatz.time_in()返回两次应用时区偏移量的结果。

Lua 脚本:

local tz=require"luatz";
require "luatz.tzcache".clear_tz_cache()
print("Before Changes (America/Los_Angeles)")
print(os.date("%H:%M",tz.time_in()))
os.execute("timedatectl set-timezone America/Chicago")
require "luatz.tzcache".clear_tz_cache()
print("America/Chicago")
print(os.date("%H:%M",tz.time_in()))
os.execute("timedatectl set-timezone America/New_York")
require "luatz.tzcache".clear_tz_cache()
print("America/New_York")
print(os.date("%H:%M",tz.time_in()))

输出:

Before Changes (America/Los_Angeles)
08:59
America/Chicago
10:59
America/New_York
11:59

实际系统本地时间:15:59

os.date背后的低级函数,localtime(3)"就像它调用tzset(3)一样",tzset使用环境变量TZ来确定时区,如果不存在,则从/etc/localtime读取。

环境变量大多在程序启动之前确定,因此,为了更改时区,您可以找到一种方法来设置TZ变量。os.setenv可通过一些 lua 库获得,例如.lua-ex

如果这似乎不是一个合理的行动方案,你也许可以确保你的脚本在没有设置TZ的情况下启动;这将迫使tzset/etc/localtime读取。可悲的是,大多数时候此文件被缓存,您将无法获得更新;这取决于您的系统。

或者,您可以使用其他库来获取时间,而不是os库。luatz您可以使用require "luatz.tzcache".clear_tz_cache()清除它的时区缓存,您可以在获取时间之前调用此函数。

相关内容

  • 没有找到相关文章

最新更新