最近在做游戏里的活动配置需求,上线后有一天运营和我说配置的时间没有失效,而在QA时明明测试过功能是正常开启的。
为此我查询了一番log,发现其中的奥秘,并直呼:坑。
其实就是一个LUA里的时间转 Unix时间戳的问题,先看以下这段代码:
date = os.time({
year=2020,month=8,day=31,hour=0,min=0,sec=0})
print(date)
-- 1598803200
然鹅,如果不了解LUA的源码可能就会踩到以下的这个坑:
local date = os.time({
year=2020,month=8,day=31})
print(date)
拍脑袋一想,这个时间戳肯定和上面的一样啊,结果发现输出的实际上是
-- 1598846400
这个其实是:
date = os.time({
year=2020,month=8,day=31,hour=12,min=0,sec=0})
print(date)
然后QA的话一般都是下午进行,所以每次配置的时候都是成功的,而在线上的时候一般是早上配置看是否能生效的,所以GG,所幸没有酿成大错。
查看相关的源码我们可以发现在loslib.c
中:
static int os_time (lua_State *L) {
time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
else {
struct tm ts;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_sec = getfield(L, "sec", 0, 0);
ts.tm_min = getfield(L, "min", 0, 0);
ts.tm_hour = getfield(L, "hour", 12, 0);
ts.tm_mday = getfield(L, "day", -1, 0);
ts.tm_mon = getfield(L, "month", -1, 1);
ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
}
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
return luaL_error(L,
"time result cannot be represented in this installation");
l_pushtime(L, t);
return 1;
}
其中时 为12。