在国内游戏开发的过程中经常会忽略时区的问题,从而导致一些玩家移动端时区设置不是UTC-8出现一些问题。
1.如何保证游戏内全部统一为服务器的时间呢
function getTimeZone()
local now = os.time()
return os.difftime(now, os.time(os.date("!*t", now)))
end
os.date("!*t", now),其中以!为关键。 “!*t” 得到的是一个 UTC 时间,为0度的经线(子午线)
北京位于东8区,所以实际的时间应该是 UTC + 8,8就是时区差 —— 8个小时。首尔位于东9区,即 UTC + 9。
服务器需要返回给客户端当前的时区的差值,比如国内就返回 8,首尔就返回 9,越南返回 7,北美返回 –16,记为 serverTimeZone。
服务端返回当前服务器时间serverTime(即北京当前时间),我们只需要将服务器时间转为 UTC 的时间,然后再加上 serverTimeZone即可。
os.time(os.date("!*t", serverTime)) + serverTimeZone * 3600
这样无论在哪个地区或国家,都将显示北京的时候,与服务器显示的时间就同步上了。
2.为什么要一直显示服务器的时间呢
游戏中有很多功能是有时间限制的,比如运营活动,或者功能开启。如果用本地时间就不好控制,统一用服务器时间避免了很多问题。
可是也容易遇到一个坑,运营配置的活动时间都是针对当前服务器的时间,例如某个活动的截止时间是:2021-06-08 00:00:00,游戏需要显示活动截止倒计时。
通常的做法: ployEndTime – serverTime,得到一个秒数,然后将秒转成:xx天xx小时xx分xx秒
serverTime 是固定的,可是ployEndTime就容易出错,为什么?
serverTime 是在东8区 —— 北京的时间,而 os.time({year=…}) 是根据本地时间来算时间的,这中间就存在问题。有一个时差的问题,之前计算一直用的是serverTimeZone —— 一个固定值,而我当前处于地区或国家,它相对于UTC的时区不确定的,怎么办?
用 (currTimeZone – serverTimeZone) * 3600 / 秒,os.time()之后再加上这个时区差就是首尔当前的时间戳了。首尔东9 - 东8 = 1,也就是要加上一个1时区,最终将得到首尔地区的时间戳,再减去 serverTime 就是剩下的秒数了,然后将它转为 xx 天 xx 小时 xx 分 xx 秒。
注意:
1)os.time({year=xx}),这个时间算出来的是针对当前所处时区的那个时间戳。
2)os.date(“!*t”, 时间戳) 得到的是UTC(时区为0)的时间戳。
3)获取当前时区的值,可以通过文章开头的 getTimeZone 方法
4)想显示固定时区的时间(例如无论在哪都显示服务器的时间),只需要将(服务器)时间戳(秒),通过第2步的方法,得到 UTC 再加上固定的时区差
5)计算倒计时的时候,需要考虑到 os.time 是取当前时区,需要再将当前时区减去目标时区,再计划时间戳