

Lua 夏令时时区问题
source link: https://luyuhuang.tech/2020/10/29/lua-dst.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Lua 夏令时时区问题
我之前的一篇文章介绍了怎样在服务器和客户端之间同步时间和时区. 同步时间相对简单些, 本质就是一个时间差; 而时区相对复杂些. 那篇文章介绍的方法有一个问题: 在客户端的时区启用了夏令时的时候, 客户端得到的本地时间会比实际快一个小时. 原因是求客户端时区的方法不对. 例如, 太平洋时区本为 UTC-0800, 而当客户端处于太平洋时区的 2020 年 10 月 29 日, 此时太平洋时区启用夏令时, 时区应为 UTC-0700. 如果使用这样的方法
local now = os_time()
local CLIENT_TIMEZONE = math.floor(os.difftime(now, os_time(os_date("!*t", now))))
求得的时区 CLIENT_TIMEZONE
的值为 -28800
, 也就是负八小时, 比实际时区少了一小时, 导致求本地时间时
function os.date(format, time)
if time == nil then
time = os.time()
end
return os_date(format, time - CLIENT_TIMEZONE + SERVER_TIMEZONE)
end
得到的时间比实际多一个小时. 为什么会有这个问题呢?
首先, 这种求时区的思路是, 先调用 os_date("!*t", now)
获取当前 UTC 时区的本地时间, 然后再调用 os_time(os_date("!*t", now))
将 UTC 时区的本地时间视为本时区的本地时间, 再转换回时间戳. 这样一来, 这个时间戳与当前时间戳的差值 os.difftime(now, os_time(os_date("!*t", now)))
就是当前时区了.
问题就出在 os_time(os_date("!*t", now))
这里. 首先我们知道调用 os.date
传入 "*t"
会得到一个表示本地时间的 table, 表示年月日时分秒等. 其中有一个不显眼的字段 isdst
, 它的含义是当前是否启用夏令时. 而调用 os_date("!*t", now)
得到 UTC 时区的本地时间, 注意 UTC 时间是永远没有夏令时的, isdst
一定是 false
. 而当我们把 UTC 时区的本地时间视为本时区的本地时间, 调用 os_time(os_date("!*t", now))
将其转换回时间戳时, 由于当前时区启用了夏令时, 这会导致其结果多出一个小时 (将非夏令时时间转换成夏令时时间, 需要加上一小时). 因此最后求的的时区就会比实际小一个小时.
解决办法也很简单. 既然减数 os_time(os_date("!*t", now))
会多出一个小时, 那么我们让被减数也多出一个小时就好了.
local now = os_time()
local utcdate = os_date("!*t", now)
local localdate = os_date("*t", now)
localdate.isdst = false
local CLIENT_TIMEZONE = math.floor(os.difftime(os_time(localdate), os_time(utcdate)))
无论当前是否是夏令时, 我们都将 localdate.isdst
置为 false
. 如果当前是夏令时, os_time(localdate)
和 os_time(utcdate)
都会多出一个小时; 如果当前不是夏令时, 它们都是准确的. 这样最终得出的时区就是准确的.
Recommend
-
77
每当别人问起怎么存储时间信息的时候,我都会告诉别人,用统一的UTC时间来存储。结果,我一直都错了。这里整理了一份对于时间存储的列表,希望能对你的时间存储行为带来最佳实践。 一定要这样做: 当需要一个确定时刻,保留一个持续化的并和夏令时无关的统一时间。G...
-
57
-
30
-
44
Java学习录 There's nothing here. Take me home.
-
25
-
7
GMT UTC CST ISO 夏令时 时间戳,都是些什么鬼?你好,我是A哥(YourBatman)。 日期/时间的处理是平时开...
-
10
摘要:主要讲述夏令时的起源,发展,标准化以及如何在GaussDB中查询任一时区的夏令时规则。本文分享自华为云社区《
-
10
提醒:北美地区今日开始实行夏令时 金融 昨天 22:48 · 亿欧 北美地区今日(13日)起开...
-
9
美国会参议院批准夏令时永久化法案-商业-金融界 美国会参议院批准夏令时永久化法案
-
17
微软警告:夏令时可能引发 Windows 7-Windows 11 出现问题 作者:潇公子 2022-09-08 09:45:12 据微软称,由于即将到来的夏令时 (DST) 时区更改,客户可能会在操作系统的各个部分遇到问题和错误 Bug。幸运的是,这...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK