(Lua) 客户端本地时间戳和服务器时间戳不一致的解决方案

问题来源:服务器的时间是固定的,国内一般都设置为北京时间(东8时区的时间),

而客户端分布在世界各地,客户端系统设置的时区是不固定的。

很多时候在设计时,没有考虑时区不一致的情况,直接使用时间戳来进行时间转换和比较,往往出现很多预想不到的问题。


基本概念/方法:

1、【时区】:全世界分24个时区,0时区是英国(格林尼治天文台旧址,经度为0,即本初子午线经过地),北京为东8区,每个相邻的时区时间相差1个小时。

2、【时间戳】:是指格林尼治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

3、获取时间戳的方法:local t = os.time()   (同一时刻任何地点的时间戳都是一样的,即相对于各时区起始时间经过的总秒数)

4、时间戳转换成字符串时间的方法:

    4.1 local timeStr = os.date("*t", timestamp)   将时间戳转换为本时区的时间table

    4.2 local timeStr = os.date("!*t", timestamp) 将时间戳转换成0时区的时间table

    4.3 local timeStr = os.date("%Y-%m-%d %H:%M:%S", timestamp) 将时间戳转换成本时区时间字符串

    其中时间table 的结构是:{year=2018,month=6,day=5,hour=12,min=2,sec=30}

5、字符串时间转时间戳的方法:

    local now = {year=2018,month=6,day=5,hour=12,min=2,sec=30}

    local timestamp = os.time(now)


因此,在此给出服务器时区和客户端时区不一致的终极解决方案:

1、服务器固定为北京时区时间,所有使用的时间戳以及yyyymmdd类似的时间字符串,都是北京时间。

2、整个应用/游戏所显示的时间、用于计算的时间都统一使用北京时间。

3、时间戳转字符串时,都换算并显示为北京时间

4、字符串转时间戳时,都转为北京时区该时间点的时间戳


详细代码和验证方法如下:

一、获得此刻北京时区的时间字符串

    local t = os.time()      -- 时间戳  

    t = t + 8 * 60 * 60     -- 加上北京时区与0时区的时间差

    local now = os.date("!*t", t)  -- 获得此刻0时区的时间结构体,即可显示为当时北京时区的时间

验证(在命令行输入 lua 回车后,进入lua模式,在运行如下脚本)

t = os.time()

t = t + 28800

now = os.date("!*t", t) 

print(string.format("%04d-%02d-%02d %02d:%02d:%02d", now.year, now.month, now.day, now.hour, now.min, now.sec))


二、获得本时区与北京时区的时间差

local function GetTimeDiff()

    local t = os.time()    -- 时间戳

    local shicha = 28800 - os.difftime(now, os.time(os.date("!*t", now))) -- 计算时差

    return shicha

end

三、时间戳转字符串

3.1 当使用os.date(“%Y-%m-%d %H:%M:%S”, timeStamp + shicha) 进行格式化时间戳时,需要加上与北京时区的时间差,

    local shicha = GetTimeDiff()

    local timeStr = os.date(“%Y-%m-%d %H:%M:%S”,  os.time() + shicha)

3.2 不能直接用 os.date(format, os.time())  或 os.date(*t, os.time()) 来企图获得北京时区的时间字符串

四、时间字符串转 时间戳时
先计算出本时区与北京时区的时间差
再算出时间字符串的本时区时间戳
然后加上 与北京时区的时差
结果就是北京时间的时间戳
    local shicha = os.difftime(now, os.time(os.date("!*t", now))) - 28800
    local now = {year=2018, month=6, day=4, hour=14, min=44, sec=30}
    local t = os.time(now) + shicha


验证:
1、系统时区设置为北京时间
2、计算指定时间的时间戳
bjtime = {year=2018, month=6, day=4, hour=14, min=44, sec=30}
t = os.time(bjtime)
print(t)    
==> 1528094670   (北京时区的时间戳)
3、切换系统时区
4、计算时间差
now = os.time()
shicha = os.difftime(now, os.time(os.date("!*t", now))) - 28800
5、计算该时间点的本地时间戳
t = os.time(bjtime)
t = t + shicha
print(t)
==> 1528094670.0   (与北京时间的时间戳一致)


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值