Lua游戏开发之时区问题

栏目: Lua · 发布时间: 5年前

内容简介:目前大部分游戏都采用了Lua语言进行功能开发,在进行多语种发行的时候就会遇到时区显示的问题。以韩国版本为例,场景如下:1、服务器处于固定的位置,比如放在首尔机房;2、玩家所处的位置不确定,可能在韩国,或者是出差在其它国家或地区;

目前大部分游戏都采用了 Lua 语言进行功能开发,在进行多语种发行的时候就会遇到时区显示的问题。以韩国版本为例,场景如下:

1、服务器处于固定的位置,比如放在首尔机房;

2、玩家所处的位置不确定,可能在韩国,或者是出差在其它国家或地区;

需求:

无论在哪个国家或地区,统一显示服务器的当前时间。在PC上查看,即便在国内测试的时候也显示韩国首尔的时间(比北京时间快1个小时)。

实现:

-- 北京时间
local serverTime = 1536722753 -- 2018/09/12 11:25

function getTimeZone()
    local now = os.time()
    return os.difftime(now, os.time(os.date("!*t", now)))
end

-- 8 hour * 3600 seconds = 28800 seconds
local timeZone = getTimeZone()/ 3600

print("timeZone : " .. timeZone)



local timeInterval = os.time(os.date("!*t", serverTime)) + timeZone * 3600 + (os.date("*t", time).isdst and 1 or 0) * 3600

local timeTable = os.date("*t", timeInterval)

--[[
for k, v in pairs(timeTable) do
    print(k .. ":" .. tostring(v))
end
]]

print(timeTable.year .. "/" .. timeTable.month .. "/" .. timeTable.day .. " " .. timeTable.hour .. ":" .. timeTable.min .. ":" .. timeTable.sec)

关注是这个方法: os.date("!*t", now),其中以!为关键。

lua 源码, loslib.c Line 283 行

static int os_date (lua_State *L) {
  size_t slen;
  const char *s = luaL_optlstring(L, 1, "%c", &slen);
  time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
  const char *se = s + slen;  /* 's' end */
  struct tm tmr, *stm;
  if (*s == '!') {  /* UTC? */
    stm = l_gmtime(&t, &tmr);
    s++;  /* skip '!' */
  }
  else
    stm = l_localtime(&t, &tmr);
  if (stm == NULL)  /* invalid date? */
    luaL_error(L, "time result cannot be represented in this installation");
  if (strcmp(s, "*t") == 0) {
    lua_createtable(L, 0, 9);  /* 9 = number of fields */
    setallfields(L, stm);
  }
  else {
    char cc[4];  /* buffer for individual conversion specifiers */
    luaL_Buffer b;
    cc[0] = '%';
    luaL_buffinit(L, &b);
    while (s < se) {
      if (*s != '%')  /* not a conversion specifier? */
        luaL_addchar(&b, *s++);
      else {
        size_t reslen;
        char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
        s++;  /* skip '%' */
        s = checkoption(L, s, se - s, cc + 1);  /* copy specifier to 'cc' */
        reslen = strftime(buff, SIZETIMEFMT, cc, stm);
        luaL_addsize(&b, reslen);
      }
    }
    luaL_pushresult(&b);
  }
  return 1;
}

从源码可以看到 ! 调用了

#define l_gmtime(t,r)        gmtime_r(t,r)

gmtime_r 函数是标准的POSIX函数,它是线程安全的,将日历时间转换为用UTC时间表示的时间。

注:UTC —— 协调世界时,又称世界统一时间、世界标准时间

也就是说 “!*t” 得到的是一个 UTC 时间,为0度的经线(子午线),亦称本初子午线,通常将它与GMT视作等同(但是UTC更为科学和精确)。

Lua游戏开发之时区问题

Lua游戏开发之时区问题

首尔位于东9区,所以实际的时间应该是 UTC + 9,9就是时区差 —— 9个小时。北京位于东8区,即 UTC + 8。

如何保证游戏内全部统一为服务器的时间呢?

服务器需要返回给客户端当前的时区的差值,比如韩国就返回 9,国内就返回 8,越南返回 7,北美返回 –16,记为 serverTimeZone。

服务端返回当前服务器时间serverTime(即首尔当前时间),我们只需要将服务器时间转为 UTC 的时间,然后再加上 serverTimeZone即可。

os.time(os.date("!*t", serverTime)) + serverTimeZone * 3600

这样无论在哪个地区或国家,都将显示首尔的时候,与服务器显示的时间就同步上了。

为什么要一直显示服务器的时间呢?

游戏中有很多功能是有时间限制的,比如运营活动,或者功能开启。如果用本地时间就不好控制,统一用服务器时间避免了很多问题。

可是也容易遇到一个坑,运营配置的活动时间都是针对当前服务器的时间,例如某个活动的截止时间是:2018-10-08 00:00:00,游戏需要显示活动截止倒计时。

通常的做法: ployEndTime – serverTime,得到一个秒数,然后将秒转成:xx天xx小时xx分xx秒

serverTime 是固定的,可是ployEndTime就容易出错,为什么?

serverTime 是在东9区 —— 首尔的时间,而 os.time({year=…}) 是根据本地时间来算时间的,这中间就存在问题。有一个时差的问题,之前计算一直用的是serverTimeZone —— 一个固定值,而我当前处于地区或国家,它相对于UTC的时区不确定的,怎么办?

用 (currTimeZone – serverTimeZone) * 3600 / 秒,os.time()之后再加上这个时区差就是首尔当前的时间戳了。国内东8 - 东9  = -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 是取当前时区,需要再将当前时区减去目标时区,再计划时间戳


以上所述就是小编给大家介绍的《Lua游戏开发之时区问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

屏幕上的聪明决策

屏幕上的聪明决策

Shlomo Benartzi、Jonah Lehrer / 石磊 / 北京联合出版公司 / 2017-3 / 56.90

 为什么在手机上购物的人,常常高估商品的价值?  为什么利用网络订餐,人们更容易选择热量高的食物?  为什么网站上明明提供了所有选项,人们却还是选不到最佳的方案?  屏幕正在改变我们的思考方式,让我们变得更冲动,更容易根据直觉做出反应,进而做出错误的决策。在《屏幕上的聪明决策》一书中,什洛莫·贝纳茨教授通过引人入胜的实验及案例,揭示了究竟是什么影响了我们在屏幕上的决策。 ......一起来看看 《屏幕上的聪明决策》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具