-- 打印表格 function PrintTable(t, indent, done) --print ( string.format ('PrintTable type %s', type(keys)) ) if type(t) ~= "table" then return end done = done or {} done[t] = true indent = indent or 0 local l = {} for k, v in pairs(t) do table.insert(l, k) end table.sort(l) for k, v in ipairs(l) do -- Ignore FDesc if v ~= 'FDesc' then local value = t[v] if type(value) == "table" and not done[value] then done [value] = true print(string.rep ("\t", indent)..tostring(v)..":") PrintTable (value, indent + 2, done) elseif type(value) == "userdata" and not done[value] then done [value] = true print(string.rep ("\t", indent)..tostring(v)..": "..tostring(value)) PrintTable ((getmetatable(value) and getmetatable(value).__index) or getmetatable(value), indent + 2, done) else if t.FDesc and t.FDesc[v] then print(string.rep ("\t", indent)..tostring(t.FDesc[v])) else print(string.rep ("\t", indent)..tostring(v)..": "..tostring(value)) end end end end end -- ***** string 功能扩展开始 ****** -- RC4 -- http://en.wikipedia.org/wiki/RC4 function RC4encrypt(text,key) function KSA(key) local key_len = string.len(key) local S = {} local key_byte = {} for i = 0, 255 do S[i] = i end for i = 1, key_len do key_byte[i-1] = string.byte(key, i, i) end local j = 0 for i = 0, 255 do j = (j + S[i] + key_byte[i % key_len]) % 256 S[i], S[j] = S[j], S[i] end return S end function PRGA(S, text_len) local i = 0 local j = 0 local K = {} for n = 1, text_len do i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] K[n] = S[(S[i] + S[j]) % 256] end return K end function RC4(key, text) local text_len = string.len(text) local S = KSA(key) local K = PRGA(S, text_len) return output(K, text) end function output(S, text) local len = string.len(text) local c = nil local res = {} for i = 1, len do c = string.byte(text, i, i) res[i] = string.char(bxor(S[i], c)) end return table.concat(res) end ------------------------------- -------------bit wise----------- ------------------------------- local bit_op = {} function bit_op.cond_and(r_a, r_b) return (r_a + r_b == 2) and 1 or 0 end function bit_op.cond_xor(r_a, r_b) return (r_a + r_b == 1) and 1 or 0 end function bit_op.cond_or(r_a, r_b) return (r_a + r_b > 0) and 1 or 0 end function bit_op.base(op_cond, a, b) -- bit operation if a < b then a, b = b, a end local res = 0 local shift = 1 while a ~= 0 do r_a = a % 2 r_b = b % 2 res = shift * bit_op[op_cond](r_a, r_b) + res shift = shift * 2 a = math.modf(a / 2) b = math.modf(b / 2) end return res end function bxor(a, b) return bit_op.base('cond_xor', a, b) end function band(a, b) return bit_op.base('cond_and', a, b) end function bor(a, b) return bit_op.base('cond_or', a, b) end local textLen = string.len(text) local schedule = KSA(key) local k = PRGA(schedule, textLen) return output(k, text) end --将字符串按格式转为16进制串 function string.tohex(str) --判断输入类型 if (type(str)~="string") then return nil,"string2hex invalid input type" end --拼接字符串 local index=1 local ret="" for index=1,str:len() do ret=ret..string.format("%02X",str:sub(index):byte()) end return ret end --将16进制串转换为字符串 function string.fromhex(hex) --判断输入类型 if (type(hex)~="string") then return nil,"hex2string invalid input type" end --滤掉分隔符 hex=hex:gsub("[%s%p]",""):upper() --检查内容是否合法 if(hex:find("[^0-9A-Fa-f]")~=nil) then return nil,"hex2string invalid input content" end --检查字符串长度 if(hex:len()%2~=0) then return nil,"hex2string invalid input lenth" end --拼接字符串 local index=1 local ret="" for index=1,hex:len(),2 do ret=ret..string.char(tonumber(hex:sub(index,index+1),16)) end return ret end -- 字符串编码 function string.encode(text, key) if text == nil or string.len(text) == 0 then return text end return string.tohex(RC4encrypt(text, key)) end -- 字符串解码 function string.decode(text, key) if text == nil or string.len(text) == 0 then return text end local s,e = string.fromhex(text) if s == nil then return s,e else return RC4encrypt(s, key) end end -- 字符串分割,返回分割后子串数组 function string.split(input, delimiter) input = tostring(input) delimiter = tostring(delimiter) if (delimiter=='') then return false end local pos,arr = 0, {} for st,sp in function() return string.find(input, delimiter, pos, true) end do table.insert(arr, string.sub(input, pos, st - 1)) pos = sp + 1 end table.insert(arr, string.sub(input, pos)) return arr end -- 字符串输出到文件 function string.tofile(str, path) local out = io.open(path,"w") if out then out:write(str) out:close() end end -- 超长字符串格式化的方式输出到文件,使用方法 table.concat(t) function string.tablefile(str, path) local out = io.open(path,"w") if out then out:write('{\n') local len = string.len(str) local step = 255 local n = math.floor(len/step) for i=0,n-1 do out:write(' "'..string.sub(str, i*step+1, (i+1)*step)..'",\n') end out:write(' "'..string.sub(str, n*step+1, (n+1)*step)..'"\n}') out:close() end end -- 从kv文件中载入字符串,对应 string.savekvfile 的输出 function string.loadkvfile(path) local t = LoadKeyValues(path) if t == nil or t["1"] == nil then return nil end local ret = t["1"] local i = 2 while(t[tostring(i)] ~= nil) do ret = ret..t[tostring(i)] i = i + 1 end t = {} return ret end --[[ 以字符串内容写入文件,成功返回 true,失败返回 false "mode 写入模式" 参数决定 io.writefile() 如何写入内容,可用的值如下: - "w+" : 覆盖文件已有内容,如果文件不存在则创建新文件 - "a+" : 追加内容到文件尾部,如果文件不存在则创建文件 此外,还可以在 "写入模式" 参数最后追加字符 "b" ,表示以二进制方式写入数据,这样可以避免内容写入不完整。 - 默认值为 "w+b" path 文件完全路径 content 要写入的内容 --]] function string.writefile(content, path, mode) mode = mode or "w+b" local file = io.open(path, mode) if file then if file:write(content) == nil then return false end io.close(file) return true else return false end end -- ***** string 功能扩展结束 ****** -- ***** table 功能扩展开始 ****** -- table和string的互转 function table.tostring(t) function ToStringEx(value) if type(value)=='table' then return table.tostring(value) elseif type(value)=='string' then return "\'"..value.."\'" else return tostring(value) end end if t == nil then return "" end local retstr= "{" local i = 1 for key,value in pairs(t) do local signal = "," if i==1 then signal = "" end if key == i then retstr = retstr..signal..ToStringEx(value) else if type(key)=='number' or type(key) == 'string' then retstr = retstr..signal..'['..ToStringEx(key).."]="..ToStringEx(value) else if type(key)=='userdata' then retstr = retstr..signal.."*s"..table.tostring(getmetatable(key)).."*e".."="..ToStringEx(value) else retstr = retstr..signal..key.."="..ToStringEx(value) end end end i = i+1 end retstr = retstr.."}" return retstr end -- table和string的互转 function table.fromstring(str) if str == nil or type(str) ~= "string" then return end -- loadstring在lua5.2中已经被弃用了 -- return loadstring("return " .. str)() return load("return " .. str)() end -- table按键名排序遍历,默认为升序 -- t为table, method为排序方式,asc或desc,func为遍历回调 -- lua中table是按照hash排列的,ipairs可以顺序遍历,但是不一定全部结果都能遍历出来,pairs能够全部遍历,但是遍历出来的结果是随机的,故需使用此方法 function table.sorteach(t, func, method) local tableTemp = {} for i in pairs(t) do if i ~= nil then table.insert(tableTemp, i) end end if method == "desc" or method == "DESC" then -- 降序 table.sort(tableTemp, function(a,b) return (a > b) end) else -- 升序 table.sort(tableTemp, function(a,b) return (a < b) end) end -- 遍历 for _, key in pairs(tableTemp) do if type(func) == "function" then func(key, t[key]) end end tableTemp = {} end -- 深度复制表 function table.deepcopy(object) local lookup_table = {} local function _copy(object) if type(object) ~= "table" then return object elseif lookup_table[object] then return lookup_table[object] end local new_table = {} lookup_table[object] = new_table for index, value in pairs(object) do new_table[_copy(index)] = _copy(value) end return setmetatable(new_table, getmetatable(object)) end return _copy(object) end -- 判断键是否在table中 function table.haskey(t, key) for k,v in pairs(t) do if k == key then return true end end return false end -- 判断值是否在table中 function table.hasvalue(t, value) for k,v in pairs(t) do if v == value then return true end end return false end -- 从文件中载入数据,来源对应加密数据 function table.loadkv(path) -- return table.fromstring(string.decode(string.loadkvfile(path), "")) return table.fromstring(string.decode(string.loadkvfile(path), SERVER_KEY)) end -- 获取表中值元素的长度,不计nil function table.count(t) if type(t) ~= "table" then return 0 end local len = 0 for k,v in pairs(t) do if v ~= nil then len = len + 1 end end return len end -- 获取表按升序排列的第index元素对应的key(排除值为nil的元素),异常返回 nil function table.getkey(t, index) if type(t) ~= "table" or index == nil then return nil end local tableTemp = {} for k in pairs(t) do if k ~= nil then table.insert(tableTemp, k) end end -- 降序 -- table.sort(tableTemp, function(a,b) return (a > b) end) -- 升序 table.sort(tableTemp, function(a,b) return (a < b) end) local key = nil local count = 0 if index >= 1 or index <= #tableTemp then key = tableTemp[index] end tableTemp = {} return key end -- 按 key 顺序循环,f为可选参数,用于指定排序顺序 function pairsByKeys(t,f) local a = {} for n in pairs(t) do a[#a + 1] = n end table.sort(a, f) local i = 0 return function() i = i + 1 return a[i], t[a[i]] end end --~ 使用上述迭代器: -- for k,v in pairsByKeys(inputTable) do -- print(k, v) -- end -- 按 key 顺序获取指定key的序号 function table.keyindex(t, key) local index = 0 for k,v in pairsByKeys(t) do index = index + 1 if k == key then return index end end return nil end -- ***** table 功能扩展结束 ****** -- ***** MD5 功能开始 ****** -- 使用 md5.sumhexa(message) md5 = { _VERSION = "md5.lua 1.1.0", _DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)", _URL = "https://github.com/kikito/md5.lua", _LICENSE = [[ MIT LICENSE Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] } -- bit lib implementions local char, byte, format, rep, sub = string.char, string.byte, string.format, string.rep, string.sub local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift local ok, bit = pcall(require, 'bit') if ok then bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift else ok, bit = pcall(require, 'bit32') if ok then bit_not = bit.bnot local tobit = function(n) return n <= 0x7fffffff and n or -(bit_not(n) + 1) end local normalize = function(f) return function(a,b) return tobit(f(tobit(a), tobit(b))) end end bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor) bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift) else local function tbl2number(tbl) local result = 0 local power = 1 for i = 1, #tbl do result = result + tbl[i] * power power = power * 2 end return result end local function expand(t1, t2) local big, small = t1, t2 if(#big < #small) then big, small = small, big end -- expand small for i = #small + 1, #big do small[i] = 0 end end local to_bits -- needs to be declared before bit_not bit_not = function(n) local tbl = to_bits(n) local size = math.max(#tbl, 32) for i = 1, size do if(tbl[i] == 1) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end -- defined as local above to_bits = function (n) if(n < 0) then -- negative return to_bits(bit_not(math.abs(n)) + 1) end -- to bits table local tbl = {} local cnt = 1 local last while n > 0 do last = n % 2 tbl[cnt] = last n = (n-last)/2 cnt = cnt + 1 end return tbl end bit_or = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if(tbl_m[i]== 0 and tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end bit_and = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if(tbl_m[i]== 0 or tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end bit_xor = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if(tbl_m[i] ~= tbl_n[i]) then tbl[i] = 1 else tbl[i] = 0 end end return tbl2number(tbl) end bit_rshift = function(n, bits) local high_bit = 0 if(n < 0) then -- negative n = bit_not(math.abs(n)) + 1 high_bit = 0x80000000 end local floor = math.floor for i=1, bits do n = n/2 n = bit_or(floor(n), high_bit) end return floor(n) end bit_lshift = function(n, bits) if(n < 0) then -- negative n = bit_not(math.abs(n)) + 1 end for i=1, bits do n = n*2 end return bit_and(n, 0xFFFFFFFF) end end end -- convert little-endian 32-bit int to a 4-char string local function lei2str(i) local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end return f(0)..f(8)..f(16)..f(24) end -- convert raw string to big-endian int local function str2bei(s) local v=0 for i=1, #s do v = v * 256 + byte(s, i) end return v end -- convert raw string to little-endian int local function str2lei(s) local v=0 for i = #s,1,-1 do v = v*256 + byte(s, i) end return v end -- cut up a string in little-endian ints of given size local function cut_le_str(s,...) local o, r = 1, {} local args = {...} for i=1, #args do table.insert(r, str2lei(sub(s, o, o + args[i] - 1))) o = o + args[i] end return r end local swap = function (w) return str2bei(lei2str(w)) end -- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh) -- 10/02/2001 jcw@equi4.com local CONSTS = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end local z=function (ff,a,b,c,d,x,s,ac) a=bit_and(a+ff(b,c,d)+x+ac,0xFFFFFFFF) -- be *very* careful that left shift does not cause rounding! return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b end local function transform(A,B,C,D,X) local a,b,c,d=A,B,C,D local t=CONSTS a=z(f,a,b,c,d,X[ 0], 7,t[ 1]) d=z(f,d,a,b,c,X[ 1],12,t[ 2]) c=z(f,c,d,a,b,X[ 2],17,t[ 3]) b=z(f,b,c,d,a,X[ 3],22,t[ 4]) a=z(f,a,b,c,d,X[ 4], 7,t[ 5]) d=z(f,d,a,b,c,X[ 5],12,t[ 6]) c=z(f,c,d,a,b,X[ 6],17,t[ 7]) b=z(f,b,c,d,a,X[ 7],22,t[ 8]) a=z(f,a,b,c,d,X[ 8], 7,t[ 9]) d=z(f,d,a,b,c,X[ 9],12,t[10]) c=z(f,c,d,a,b,X[10],17,t[11]) b=z(f,b,c,d,a,X[11],22,t[12]) a=z(f,a,b,c,d,X[12], 7,t[13]) d=z(f,d,a,b,c,X[13],12,t[14]) c=z(f,c,d,a,b,X[14],17,t[15]) b=z(f,b,c,d,a,X[15],22,t[16]) a=z(g,a,b,c,d,X[ 1], 5,t[17]) d=z(g,d,a,b,c,X[ 6], 9,t[18]) c=z(g,c,d,a,b,X[11],14,t[19]) b=z(g,b,c,d,a,X[ 0],20,t[20]) a=z(g,a,b,c,d,X[ 5], 5,t[21]) d=z(g,d,a,b,c,X[10], 9,t[22]) c=z(g,c,d,a,b,X[15],14,t[23]) b=z(g,b,c,d,a,X[ 4],20,t[24]) a=z(g,a,b,c,d,X[ 9], 5,t[25]) d=z(g,d,a,b,c,X[14], 9,t[26]) c=z(g,c,d,a,b,X[ 3],14,t[27]) b=z(g,b,c,d,a,X[ 8],20,t[28]) a=z(g,a,b,c,d,X[13], 5,t[29]) d=z(g,d,a,b,c,X[ 2], 9,t[30]) c=z(g,c,d,a,b,X[ 7],14,t[31]) b=z(g,b,c,d,a,X[12],20,t[32]) a=z(h,a,b,c,d,X[ 5], 4,t[33]) d=z(h,d,a,b,c,X[ 8],11,t[34]) c=z(h,c,d,a,b,X[11],16,t[35]) b=z(h,b,c,d,a,X[14],23,t[36]) a=z(h,a,b,c,d,X[ 1], 4,t[37]) d=z(h,d,a,b,c,X[ 4],11,t[38]) c=z(h,c,d,a,b,X[ 7],16,t[39]) b=z(h,b,c,d,a,X[10],23,t[40]) a=z(h,a,b,c,d,X[13], 4,t[41]) d=z(h,d,a,b,c,X[ 0],11,t[42]) c=z(h,c,d,a,b,X[ 3],16,t[43]) b=z(h,b,c,d,a,X[ 6],23,t[44]) a=z(h,a,b,c,d,X[ 9], 4,t[45]) d=z(h,d,a,b,c,X[12],11,t[46]) c=z(h,c,d,a,b,X[15],16,t[47]) b=z(h,b,c,d,a,X[ 2],23,t[48]) a=z(i,a,b,c,d,X[ 0], 6,t[49]) d=z(i,d,a,b,c,X[ 7],10,t[50]) c=z(i,c,d,a,b,X[14],15,t[51]) b=z(i,b,c,d,a,X[ 5],21,t[52]) a=z(i,a,b,c,d,X[12], 6,t[53]) d=z(i,d,a,b,c,X[ 3],10,t[54]) c=z(i,c,d,a,b,X[10],15,t[55]) b=z(i,b,c,d,a,X[ 1],21,t[56]) a=z(i,a,b,c,d,X[ 8], 6,t[57]) d=z(i,d,a,b,c,X[15],10,t[58]) c=z(i,c,d,a,b,X[ 6],15,t[59]) b=z(i,b,c,d,a,X[13],21,t[60]) a=z(i,a,b,c,d,X[ 4], 6,t[61]) d=z(i,d,a,b,c,X[11],10,t[62]) c=z(i,c,d,a,b,X[ 2],15,t[63]) b=z(i,b,c,d,a,X[ 9],21,t[64]) return bit_and(A+a,0xFFFFFFFF),bit_and(B+b,0xFFFFFFFF), bit_and(C+c,0xFFFFFFFF),bit_and(D+d,0xFFFFFFFF) end ---------------------------------------------------------------- local function md5_update(self, s) self.pos = self.pos + #s s = self.buf .. s for ii = 1, #s - 63, 64 do local X = cut_le_str(sub(s,ii,ii+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) assert(#X == 16) X[0] = table.remove(X,1) -- zero based! self.a,self.b,self.c,self.d = transform(self.a,self.b,self.c,self.d,X) end self.buf = sub(s, math.floor(#s/64)*64 + 1, #s) return self end local function md5_finish(self) local msgLen = self.pos local padLen = 56 - msgLen % 64 if msgLen % 64 > 56 then padLen = padLen + 64 end if padLen == 0 then padLen = 64 end local s = char(128) .. rep(char(0),padLen-1) .. lei2str(bit_and(8*msgLen, 0xFFFFFFFF)) .. lei2str(math.floor(msgLen/0x20000000)) md5_update(self, s) assert(self.pos % 64 == 0) return lei2str(self.a) .. lei2str(self.b) .. lei2str(self.c) .. lei2str(self.d) end ---------------------------------------------------------------- function md5.new() return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68], pos = 0, buf = '', update = md5_update, finish = md5_finish } end function md5.tohex(s) return format("%08x%08x%08x%08x", str2bei(sub(s, 1, 4)), str2bei(sub(s, 5, 8)), str2bei(sub(s, 9, 12)), str2bei(sub(s, 13, 16))) end function md5.sum(s) return md5.new():update(s):finish() end function md5.sumhexa(s) return md5.tohex(md5.sum(s)) end -- ***** MD5 功能结束 ****** -- ***** datetime 功能开始 ****** datetime = {} --[[ |========================================================================= | 判断是否为闰年 |========================================================================= | @param {int} year | @return boolean ]] function datetime.isLeapYear(year) return (year%4 == 0 and year%100 ~= 0) or (year%400 == 0) end --[[ |========================================================================= | 获取UNIX时间戳 |========================================================================= | 以UTC时间为标准 | | @param {string} datetime 只支持格式'2016-10-13 01:01:01' | @return int ]] function datetime.toUnixTime(datetimeString) local datetimeTable = string.split(datetimeString,' ') local datepart = string.split(datetimeTable[1],'-') local timepart = string.split(datetimeTable[2],':') local sec = tonumber(timepart[3]) + tonumber(timepart[2])*60 + tonumber(timepart[1])*60*60 + (tonumber(datepart[3]) - 1)*86400 local year = tonumber(datepart[1]) local m = tonumber(datepart[2]) - 1 for i=1,m do if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then sec = sec + 31 * 86400 elseif i==4 or i==6 or i==9 or i==11 then sec = sec + 30 * 86400 else if datetime.isLeapYear(year) then sec = sec + 29 * 86400 else sec = sec + 28 * 86400 end end end local day = 0 for i=1970,year-1 do if datetime.isLeapYear(i) then day = day + 366 else day = day + 365 end end sec = sec + day * 86400 return sec end --[[ |========================================================================= | 把UNIX时间戳转换成日期格式 |========================================================================= | 以UTC时间为标准,输出格式'2016-10-13 01:01:01' | | @param {int} unixtime | @param {boolean} [returnTable] 可选,如果为true返回table | @return string|table ]] function datetime.toDatetime(unixtime, returnTable ) local day = math.floor(unixtime/86400) local year = 1970 while day >= 365 do if datetime.isLeapYear(year) then day = day - 366 unixtime = unixtime - 366*86400 else day = day - 365 unixtime = unixtime - 365*86400 end year = year + 1 end _day = 0 local month = 0 for i=1,12 do local d if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then d = 31 elseif i==4 or i==6 or i==9 or i==11 then d = 30 else if datetime.isLeapYear(year) then d = 29 else d = 28 end end _day = _day + d if day < _day then month = i unixtime = unixtime - (_day-d)*86400 break end end day = math.floor(unixtime/86400) unixtime = unixtime - day*86400 local h = math.floor(unixtime/3600) unixtime = unixtime - h*3600 local m = math.floor(unixtime/60) unixtime = unixtime - m*60 if returnTable then return { year = year, month = month, day = day+1, hour = h, min = m, second = unixtime, } end return string.format('%d-%02d-%02d %02d:%02d:%02d',year,month,day+1,h,m,unixtime) end --[[ |========================================================================= | 获取服务器当前时间,返回标准格式时间,UNIX时间 |========================================================================= | @return string,int ]] function datetime.now() local time = math.floor(UTC_TIME + GameRules:GetGameTime()) return datetime.toDatetime(time),time end --[[ |========================================================================= | 判断星期几,默认当前时间 |========================================================================= | @param {int} week 区间[1,7] | @return boolean ]] function datetime.isWeek(week, datetimeString) local date = {} if datetimeString == nil then date = datetime.toDatetime(math.floor(UTC_TIME + GameRules:GetGameTime()),true) else date = datetime.toDatetime(datetime.toUnixTime(datetimeString),true) end local y = date.year local m = date.month local d = date.day if m == 1 or m == 2 then m = m + 12 y = y - 1 end local w = math.floor((d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) % 7) if w == 0 then w = 7 end -- print(currentWeek) return w == week end --[[ |========================================================================= | 根据日期获取星期几 返回1-7,默认当前时间 |========================================================================= | @param {table} date or string | @return int ]] function datetime.getWeek(date) if date == nil then local time = math.floor(UTC_TIME + GameRules:GetGameTime()) date = datetime.toDatetime(time,true) elseif type(date) == "string" then date = datetime.toDatetime(datetime.toUnixTime(date),true) end local y = date.year local m = date.month local d = date.day if m == 1 or m == 2 then y = y - 1 m = m + 12 end local w = (d+2*m+math.floor(3*(m+1)/5)+y+math.floor(y/4)-math.floor(y/100)+math.floor(y/400)) % 7 + 1 if w == 0 then w = 7 end return w end --[[ |========================================================================= | 判断是否当月最后一天 |========================================================================= | @return boolean ]] function datetime.isLastDay(datetimeAny) local data if type(datetimeAny) == "string" then data = datetime.toDatetime(datetime.toUnixTime(datetimeAny), true) elseif type(datetimeAny) == "table" then data = datetimeAny elseif type(datetimeAny) == "number" then data = datetime.toDatetime(datetimeAny, true) else print("Invalid datetime") end local i = data.month if i > 12 or i < 1 then print("Invalid datetime") end if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then return data.day == 31 elseif i==4 or i==6 or i==9 or i==11 then return data.day == 30 else if datetime.isLeapYear(data.year) then return data.day == 29 else return data.day == 28 end end end --[[ |========================================================================= | 获取当月最后一天,传入参数以 yyyy-MM 开头 |========================================================================= | @return boolean ]] function datetime.getLastDay(datetimeString) local i = tonumber(string.sub(datetimeString, 6, 7)) if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then return 31 elseif i==4 or i==6 or i==9 or i==11 then return 30 else if datetime.isLeapYear(tonumber(string.sub(datetimeString, 1, 4))) then return 29 else return 28 end end end --[[ |========================================================================= | 获取增加x个月后的时间,一个月按30天计算 |========================================================================= | @return string ]] function datetime.addMonth(datetimeString, month) return datetime.toDatetime(datetime.toUnixTime(datetimeString) + month * 30 * 24 * 3600) end --[[ |========================================================================= | 获取增加x天后的时间 |========================================================================= | @return string ]] function datetime.addDay(datetimeString, day) return datetime.toDatetime(datetime.toUnixTime(datetimeString) + day * 24 * 3600) end --[[ |========================================================================= | 获取两个日期相差多少天,只取日期部分 |========================================================================= | @return number ]] function datetime.getDaysByTwoDate(dateStart, dateEnd) local time1 = datetime.toUnixTime(string.sub(dateStart,1,10).." 00:00:00") local time2 = datetime.toUnixTime(string.sub(dateEnd,1,10).." 00:00:00") return math.floor((time2-time1)/(24*3600)) end --[[ |========================================================================= | 获取两个日期相差多少秒,结果可用于判定日期前后 |========================================================================= | @return number ]] function datetime.subtracte(dateStart, dateEnd) return datetime.toUnixTime(dateEnd) - datetime.toUnixTime(dateStart) end -- ***** datetime 功能结束 ******