--[[ 创建日期: 2021-9-3 创建人: HAN 名称: oi_base_func 功能: 一些常用的 Lua 函数封装 Lua Wrapper Function 简称 lwf 变更记录: V6.0 HAN 2023/9/8 V7.0 HAN 2025/1/27 从oi_basestrfunc 分离出来 --]] json = require ("json") local lua = {_version = "0.1.1"} -- 定义一个空表,用于存储模块的函数和变量 ------------------------------------------------------------------------------------------------- -- 字符串根据特殊符号reps进行分割 -- 分割为一个数组 ------------------------------------------------------------------------------------------------- function lua.split( str,reps ) local resultStrList = {} if ( reps == nil or reps == '' ) then return "" end if ( str == nil or str == '' ) then return resultStrList end string.gsub( str,'[^'..reps..']+',function ( w ) table.insert(resultStrList,w) end ) return resultStrList end ------------------------------------------------------------------------------------------------- -- 表转成字符串 ------------------------------------------------------------------------------------------------- function lua.table2str(t) local function serialize(tbl) local tmp = {} for k, v in pairs(tbl) do local k_type = type(k) local v_type = type(v) if ( v_type == "string" ) then v = string.gsub(v,'\\',"\\\\") v = string.gsub(v,'"','\\"') end local key = (k_type == "string" and "\"" .. k .. "\":") or (k_type == "number" and "") local value = (v_type == "table" and serialize(v)) or (v_type == "boolean" and tostring(v)) or (v_type == "string" and "\"" .. v .. "\"") or (v_type == "number" and v) tmp[#tmp + 1] = key and value and tostring(key) .. tostring(value) or nil end if #tbl == 0 then return "{" .. table.concat(tmp, ",") .. "}" else return "[" .. table.concat(tmp, ",") .. "]" end end assert(type(t) == "table") return serialize(t) end -- 把t2表加到t1后面 function lua.table_merge( t1, t2 ) local n for n = 1, #t2 do table.insert( t1, t2[n] ) end end function lua.table_is_empty(t) return t and next(t) == nil or true end -- 获取table的长度 function lua.GetTableCount( t ) if ( t == nil or type(t) ~= "table" ) then return 0 end return #t end --[[ 取消字符串前后的空格 --]] function lua.trim( strbuf ) if ( strbuf == nil ) then error( "trim 函数的输入参数不能为 nil!") end if ( strbuf == '' ) then return "" end return string.gsub(strbuf, '^[%s]*([^%s].*[^%s])[%s]*$', "%1") end --[[ 取消字符串前后的"",比如字符串:"ABC",执行后变成 ABC --]] function lua.trim_quotation_mark( strbuf ) if ( strbuf == nil ) then error( "trim_quotation_mark 函数的输入参数不能为 nil!") end if ( strbuf == '' ) then return "" end return string.gsub(strbuf, '^["]*([^"].*[^"])["]*$', "%1") end ------------------------------------------------------------------------------------------------- -- 把一个GUID字符串的前面和后面的 {}取消 -- 输入 strvalue = {XXXXX-XXX-XXXX} 返回 XXXXX-XXX-XXXX} ------------------------------------------------------------------------------------------------- function lua.trim_guid_str( strvalue ) if ( strvalue == nil or strvalue == '' ) then return "" end local nSize = string.len( strvalue ) if ( nSize ~= 38 ) then return strvalue end strvalue = string.sub( strvalue, 1, nSize-1 ) strvalue = string.sub( strvalue, 2, -1 ) return strvalue end --[[ 把一个字符串去头去尾,比如["A","B"],执行后变成 "A","B" --]] function lua.trim_str_head_end( strvalue ) if ( strvalue == nil or strvalue == '' ) then return "" end local nSize = string.len( strvalue ) if ( nSize < 2 ) then return strvalue end strvalue = string.sub( strvalue, 1, nSize-1 ) strvalue = string.sub( strvalue, 2, -1 ) return strvalue end ------------------------------------------------------------------------------------------------- -- 取消字符串最后面的一个符号 ------------------------------------------------------------------------------------------------- function lua.trim_laster_char( strBuf ) if ( strBuf == nil ) then return "" end local nSize = string.len(strBuf) if ( nSize == 0) then return '' end return string.sub( strBuf, 1, nSize-1 ) end ------------------------------------------------------------------------------------------------- -- 把一个字符串数组["A","B"]转成 'A','B' ------------------------------------------------------------------------------------------------- function lua.strArray2string(t) local ret_str = '' for k,v in ipairs(t) do ret_str = ret_str.."'"..v.."'," end return lua.trim_laster_char( ret_str ) end --[[ 判断 value 是否在 tbl 表中,这个tbl表是一个["a","b"]这样的数组 --]] function lua.IsInTable(value, tbl) for k,v in ipairs(tbl) do if v == value then return true; end end return false; end -- 判断表是否为空表 function lua.IsTableEmpty(t) if t == nil or next(t) == nil then return true else return false end end -- 加一个字符串到一个字符串数组,如果数组里存在这个字符串就不增加 function lua.Add_StrArray( strArray, strValue ) local n if ( type(strArray) ~= "table" ) then return end if ( strValue == nil or strValue == '' ) then return end for n = 1, #strArray do if (strArray[n] == strValue ) then return end end n = #strArray + 1 strArray[n] = strValue end -- 浮点数相等 function lua.equation( f1, f2 ) return math.abs( f1 - f2 ) < 0.000001 end --[[ 时间的加减计算 srcDateTime -- 日期时间 interval -- 加减值 dateUnit -- 计算事件单位 DAY 天 HOUR 小时 MINUTE 分钟 SECOND 秒 --]] function lua.getNewDate( srcDateTime, interval ,dateUnit ) local Y = string.sub(srcDateTime,1,4) local M = string.sub(srcDateTime,5,6) local D = string.sub(srcDateTime,7,8) local H = string.sub(srcDateTime,9,10) local MM = string.sub(srcDateTime,11,12) local SS = string.sub(srcDateTime,13,14) local dt1 = os.time{year=Y, month=M, day=D, hour=H,min=MM,sec=SS} local ofset=0 if dateUnit =='DAY' then ofset = 60 *60 * 24 * interval elseif dateUnit == 'HOUR' then ofset = 60 *60 * interval elseif dateUnit == 'MINUTE' then ofset = 60 * interval elseif dateUnit == 'SECOND' then ofset = interval end local newTime = os.date("*t", dt1 + tonumber(ofset)) return newTime end --[[ 计算两个日期之间的天数 --]] function lua.dateDiff(date1,date2) local day1 = {}; local day2 = {}; local numDay1; local numDay2; if date1 < 19700101 or date2 < 19700101 then return 0; end day1.year,day1.month,day1.day = string.match(date1,"(%d%d%d%d)(%d%d)(%d%d)"); day2.year,day2.month,day2.day = string.match(date2,"(%d%d%d%d)(%d%d)(%d%d)"); numDay1 = os.time(day1); numDay2 = os.time(day2); return (numDay1-numDay2)/(3600*24); end -- 根据年月日获取是星期几 -- 输入 strDate 2021-9-7 -- 返回星期几 function lua.getWeekNum(strDate) if ( strDate == '' or strDate == nil ) then return 0 end local ymd = lua.split(strDate,"-") if ( ymd == nil or #ymd ~= 3 ) then return 0 end t = os.time({year=tostring(ymd[1]),month=tostring(ymd[2]),day=tostring(ymd[3])}) local weekNum = os.date("*t",t).wday -1 if weekNum == 0 then weekNum = 7 end return weekNum end -- 把时间字符串转 os.time 输入:2024-9-12 8:20:10 function lua.toTimestamp(dateStr) local pattern = "(%d+)%-(%d+)%-(%d+) (%d+):(%d+):(%d+)" local year, month, day, hour, min, sec = dateStr:match(pattern) return os.time({day=day, month=month, year=year, hour=hour, min=min, sec=sec}) end -- 比较两个日期字符串 function lua.DateTimeIsBefore( dateStr1, dateStr2 ) local timestamp1 = lua.toTimestamp(dateStr1) local timestamp2 = lua.toTimestamp(dateStr2) return timestamp1 < timestamp2 end --[[ 日期格式转换 输入 2021/9/2 2021-9-2 2021.9.2 转化为 2021-09-02 --]] function lua.DayFormatConversion( strDay ) local seg = {} seg = lua.split( strDay, '/' ) local nCount nCount = #seg if ( nCount == 1 ) then seg = lua.split( strDay, '-' ) nCount = #seg if ( nCount == 1 ) then seg = lua.split( strDay, '.' ) nCount = #seg end end if ( nCount ~= 3 ) then return 1, "日期格式不正确!" end local nYear = tonumber( seg[1] ) local nMonth = tonumber( seg[2] ) local nDay = tonumber( seg[3] ) strDays = string.format( '%d-%02d-%02d', nYear, nMonth, nDay ) return 0, strDays end -- 规整日期时间格式,输入 2024-1-20 8:20:1 变成 2024-01-20 08:20:01 -- 如果格式匹配不上返回 1,正确返回 0,第二个参数是规整过后的时间 function lua.Regular_Datetime( str_datetime ) local pattern = "(%d+)%-(%d+)%-(%d+) (%d+):(%d+):(%d+)" local year, month, day, hour, min, sec = str_datetime:match(pattern) if (year == nil) then return 1, "输入格式非法,格式要求是: 2024-11-30 8:20:1" end return 0, string.format( '%d-%02d-%02d %02d:%02d:%02d', year, month, day, hour, min, sec ) end --[[ 日期格式转换 输入 20210902 转化为 2021-09-02 --]] function lua.DayFormatConversion2( strDay ) local nSize = string.len( strDay ) if ( nSize ~= 8 ) then return 1, "日期格式不正确!" end local strYear = string.sub( strDay, 1, nSize-4 ) local strMonth = string.sub( strDay, 5, 6 ) local strDay = string.sub( strDay, 7, 8 ) local nYear = tonumber( strYear ) local nMonth = tonumber( strMonth ) local nDay = tonumber( strDay ) local strNewDay = string.format( '%d-%02d-%02d', nYear, nMonth, nDay ) return 0, strNewDay end --[[ 计算某天是星期几 --]] function lua.CalculateWeekNumber( nYear, nMonth, nDay ) return os.date("%W",os.date(os.time{year=nYear,month=nMonth,day=nDay})) end -- 生成一个 GUID function lua.guid() local seed={'e','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} local tb={} for i=1,32 do table.insert(tb,seed[math.random(1,16)]) end local sid=table.concat(tb) return string.format('%s-%s-%s-%s-%s', string.sub(sid,1,8), string.sub(sid,9,12), string.sub(sid,13,16), string.sub(sid,17,20), string.sub(sid,21,32) ) end --[[ 把数值转换成大写中文数字: 12080 壹万贰仟零捌拾 --]] function lua.finance_format(szNum) local szChMoney = "" local iLen = 0 local iNum = 0 local iAddZero = 0 local hzUnit = {"", "十", "百", "千", "万", "十", "百", "千", "亿","十", "百", "千", "万", "十", "百", "千"} local hzNum = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"} if nil == tonumber(szNum) then return tostring(szNum) end if ( type(szNum) == "number" ) then szNum = tostring(szNum) end iLen =string.len(szNum) if iLen > 10 or iLen == 0 or tonumber(szNum) < 0 then return tostring(szNum) end for i = 1, iLen do iNum = string.sub(szNum,i,i) if iNum == 0 and i ~= iLen then iAddZero = iAddZero + 1 else if iAddZero > 0 then szChMoney = szChMoney..hzNum[1] end szChMoney = szChMoney..hzNum[iNum + 1] --//转换为相应的数字 iAddZero = 0 end if (iAddZero < 4) and (0 == (iLen - i) % 4 or 0 ~= tonumber(iNum)) then szChMoney = szChMoney..hzUnit[iLen-i+1] end end return szChMoney end --[[ 根据输入的字符串获取年月日 如:输入 2021-09-10 返回 2021,9, 10 --]] function lua.GetYearMonthDay( strDay ) local seg = {} if ( strDay == '' or strDay == nil ) then return 2, "GetYearMonthDay 输入参数不能为空!","","" end seg = lua.split( strDay, "-" ) if ( #seg ~= 3 ) then return 2, "GetYearMonthDay 格式非法!"..strDay,"","" end return 0, tonumber( seg[1] ), tonumber( seg[2] ), tonumber( seg[3] ) end --[[ 计算两个日期差几天 建议取消:HAN 2024-2-11 --]] function lua.time_diff(start_time, end_time) local t1 = os.date("%Y%m%d", start_time) local t2 = os.date("%Y%m%d", end_time) local day1 = {} local day2 = {} day1.year,day1.month,day1.day = string.match(t1,"(%d%d%d%d)(%d%d)(%d%d)") day2.year,day2.month,day2.day = string.match(t2,"(%d%d%d%d)(%d%d)(%d%d)") local numDay1 = os.time(day1) local numDay2 = os.time(day2) return (numDay2 - numDay1)/(3600*24) end --[[ 数组里增加一个值,如果这个值不存在就新增 --]] function lua.AddArray( array, value ) local k, v local exist = 0 for k,v in ipairs(array) do if ( v == value ) then exist = 1 break end end if ( exist == 0 ) then table.insert( array, value ) end end --[[ 获取文件名 strPathFileName --"C:/Windows/assembly/temp.lua" --]] function lua.getFileNameInPath ( strPathFileName ) local ts = string.reverse( strPathFileName ) local i = string.find ( ts, "/" ) if ( i == 0 or i == nil ) then return 1, "文件名格式不符合要求!" end local nSize = string.len(ts) local m = nSize - i + 1 return 0, string.sub(strPathFileName, m+1, nSize) end --[[ 如果要把一个字符串加入到 json 中, 如果字符串本身带 " 符号回造成JSON格式错误,因此必须要把"替换掉 另外,如果对字符串的长度有要求,也需要进行裁剪 另外返回的字符串中有的特殊字符串要把<>替换成 《》 建议取消: HAN 2024-2-11 ]] function lua.proJsonStrNode( strJson, nLen ) -- 把字符串中的"取消,用'替换 strJson = string.gsub(strJson, '"',"'") -- 返回信息中的处理把 <> 替换 strJson = string.gsub(strJson, '<',"《") strJson = string.gsub(strJson, '>',"》") if (#strJson > nLen ) then strJson = string.sub( strJson, 1, nLen ) end return strJson end --[[ FormatJsonString,在设置属性时我们一般会用到 "attr":"xxx","value":"strValue" 如果 strValue 里有 " 系统会出错,因此 --]] function lua.FormatJsonString( strJson ) return string.gsub(strJson, '"','\\\"') end --[[ FormatSQLString,把字符加入SQL语句前把 ' 符号用"进行替换否则SQL会出错 --]] function lua.FormatSQLString( strSQL ) return string.gsub(strSQL, "'",'"') end --[[ 返回一个 {"attr":“xxx”,"value":"xxx"} 的JSON对象 -- 不建议使用 --]] function lua.KeyValueObj( strAttr, strValue ) local key_value = {} strAttr = lua.trim( strAttr ) key_value.attr = strAttr key_value.value = tostring(strValue) return key_value end --[[ 截掉字符串开头的某个字符,比如输入的字符串 = 000232G090 需要截掉开始的 000 trime_char -- 需要截掉的字符 --]] function lua.TrimStrHead( str, trim_char ) local n,nCount, m local ascii = string.byte( trim_char ) nCount = string.len(str) m = 0 if (string.byte( str,1) == ascii) then for n = 2, nCount do if (string.byte( str,n ) ~= ascii ) then m = n break end end if ( m ~= 0 ) then str = string.sub( str, m, -1) end end return str end --[[ 如果输入字符串的长度不够nLen,用 cFill 字符在前面进行填充 --]] function lua.strFill( str, nLen, cFill ) local nSize = #str local strHead = '' if (nSize >= nLen) then return str end local n, nCount nCount = nLen - nSize for n = 1, nCount do strHead = strHead..cFill end return strHead..str end --[[ 输入月份返回这个月份是第几个季度 --]] function lua.month_to_quarter(month) if month < 1 or month > 12 then return -1 -- 无效的月份 elseif month >= 1 and month <= 3 then return 1 -- 第一季度 elseif month >= 4 and month <= 6 then return 2 -- 第二季度 elseif month >= 7 and month <= 9 then return 3 -- 第三季度 else return 4 -- 第四季度 end end -- 字符串转数值,如果是空字符串返回0 function lua.StrToNumber( strValue ) if ( strValue == '' or strValue == nil ) then return 0 end return tonumber( strValue ) end -- 从json对象中获取属性 function lua.Get_StrAttrValue( value ) if ( value == nil ) then return "" end return value end -- 从json对象中获取属性 function lua.Get_NumAttrValue( value ) if ( value == '' or value == nil ) then return 0 end local attr_type = type(value) if ( attr_type == "number" ) then return value end if ( attr_type == "string") then return tonumber( value ) end return 0 end function lua.Get_BoolAttrValue( value ) if ( value == '' or value == nil ) then return false end if ( type(value) == "boolean" ) then return value end return false end -- 输出日志文件 -- XX function lua.WriteLog(strLuaDEID, logType, lua_file, line, key, value) local day_hour = os.date("%Y%m%d%H") local curTime = os.date("%Y-%m-%d %H:%M:%S") local nRet, strRetInfo if ( value == nil ) then value = '' end nRet, strRetInfo = mobox.getLuaDEInfo(strLuaDEID) if (nRet ~= 0 or strRetInfo == '') then return end local lua_info, success success, lua_info = pcall( json.decode, strRetInfo) if ( success == false ) then return end local strLog = strLuaDEID.."|"..logType.."|"..lua_info.class_name.."|"..lua_info.event_source.."|"..lua_info.event_name.."|"..lua_info.event_code.."|"..lua_file.."|"..line.."|"..lua_info.user_name.."|"..key.."|"..value nRet = mobox.writeLuaLog( strLog ) end local function get_filename_line( debug_info ) local line = 0 local lua_file = '' if (debug_info == nil or type(debug_info) ~= "table" ) then return 0,"" else local pos1, pos3 line = debug_info.currentline if (line == nil) then line = 0 end lua_file = debug_info.short_src pos1, pos2 = string.find(lua_file, ".lua") if (lua_file == nil or pos1 == nil) then lua_file = '' end end return line, lua_file end function lua.Wait( strLuaDEID, strMsg ) -- 4 条件不具备,等待后续处理 mobox.setInfo( strLuaDEID, strMsg ) mobox.returnValue( strLuaDEID, 0, "", 4 ) end -- strLuaCode Lua 脚本编码 line 第几行 key -- 属性 value 值 -- 主要用于调试的时候脚本输出 -- 输出:Lua_Debug|时间|strLuaDEID|类型|数据类|事件名称|事件编码|第几行|操作者|属性|值 function lua.Debug( strLuaDEID, debug_info, key, value ) local line = 0 local lua_file = '' if( type(value) == "table" and value.cls ~= nil ) then local nRet nRet, value = mobox.formatLuaJson( lua.table2str(value) ) end if ( value == nil ) then error( "Debug 函数中value值不能是nil") end local value_type = type(value) if ( value_type == "boolean") then if ( value ) then value = "true" else value = "false" end elseif ( value_type == "table") then value = lua.table2str( value ) end line, lua_file = get_filename_line( debug_info ) local day_hour = os.date("%Y%m%d%H") local curTime = os.date("%Y-%m-%d %H:%M:%S") local nRet, strRetInfo nRet, strRetInfo = mobox.getLuaDEInfo(strLuaDEID) if (nRet ~= 0 or strRetInfo == '') then error( "WriteLog 函数调用 getLuaDEInfo 失败!"..strRetInfo ) end local lua_info, success success, lua_info = pcall( json.decode, strRetInfo) if ( success == false ) then error( "Lua数据包的JSON格式非法! 原因:"..lua_info..' --> '..strRetInfo ) end -- 如果设置了不显示Debug信息,马上返回 if (lua_info.gen_lua_log == 0 ) then return end local strLog = strLuaDEID.."|调试|"..lua_info.class_name.."|"..lua_info.event_source.."|"..lua_info.event_name.."|"..lua_info.event_code.."|"..lua_file.."|"..line.."|"..lua_info.user_name.."|"..key.."|"..value nRet = mobox.writeLuaLog( strLog ) if ( nRet ~= 0 ) then error( "writeLuaLog失败!" ) end end -- DebugEx 和 Debug的区别是少输入一个 debug.getinfo , 效率比 Debug 要高一些 -- 建议用这个函数 -- 主要用于调试的时候脚本输出 -- 输出:Lua_Debug|时间|strLuaDEID|类型|数据类|事件名称|事件编码|第几行|操作者|属性|值 function lua.DebugEx( strLuaDEID, key, value ) local line = 0 local lua_file = '' local nRet, strRetInfo nRet, strRetInfo = mobox.getLuaDEInfo(strLuaDEID) if (nRet ~= 0 or strRetInfo == '') then return end local lua_info, success success, lua_info = pcall( json.decode, strRetInfo) if ( success == false ) then return end if ( lua_info.gen_lua_info == 0 ) then return end local debug_info = debug.getinfo(2) if( type(value) == "table" and value.cls ~= nil ) then local nRet nRet, value = mobox.formatLuaJson( lua.table2str(value) ) end if ( value == nil ) then value = "nil" end local value_type = type(value) if ( value_type == "boolean") then if ( value ) then value = "true" else value = "false" end elseif ( value_type == "table") then value = lua.table2str( value ) end line, lua_file = get_filename_line( debug_info ) local day_hour = os.date("%Y%m%d%H") local curTime = os.date("%Y-%m-%d %H:%M:%S") local strLog = strLuaDEID.."|调试|"..lua_info.class_name.."|"..lua_info.event_source.."|"..lua_info.event_name.."|"..lua_info.event_code.."|"..lua_file.."|"..line.."|"..lua_info.user_name.."|"..key.."|"..value nRet = mobox.writeLuaLog( strLog ) --if ( nRet ~= 0 ) then error( "writeLuaLog失败!" ) end end -- 设置mobox.stopProgram function lua.Stop( strLuaDEID, msg ) local line = 0 local lua_file = '' nRet, strRetInfo = mobox.getLuaDEInfo(strLuaDEID) if (nRet ~= 0 or strRetInfo == '') then return end local lua_info, success success, lua_info = pcall( json.decode, strRetInfo) if ( success == false ) then return end local debug_info = debug.getinfo(2) line, lua_file = get_filename_line( debug_info ) local str_msg = "在编码'"..lua_info.event_code.."' 名称:',"..lua_info.event_name.."'的脚本中第("..line..")行终止执行,原因:"..msg if ( lua_info.gen_lua_info == 0 ) then -- 不输出 Debug 信息,那么在客户端就不要显示 错误行信息,把错误信息作为警告输出 mobox.stopProgram( strLuaDEID, msg ) lua.WriteLog( strLuaDEID, "警告", lua_file, line, "", str_msg ) else mobox.stopProgram( strLuaDEID, str_msg ) end end -- 用于输出Lua脚本执行时的警告信息 warning function lua.Warning( strLuaDEID, debug_info, warnInfo ) local line = 0 local lua_file = '' line, lua_file = get_filename_line( debug_info ) lua.WriteLog( strLuaDEID, "警告", lua_file, line, "", warnInfo) end -- 用于输出Lua脚本执行时的错误信息 errorInfo function lua.Error( strLuaDEID, debug_info, errorInfo ) local line = 0 local lua_file = '' line, lua_file = get_filename_line( debug_info ) lua.WriteLog( strLuaDEID, "错误", lua_file, line, "", errorInfo) error( errorInfo ) end -- 把字符 Y 转成 true N 转成false -- XX function lua.YesNo2Bool( strYesNo ) if ( strYesNo == nil or strYesNo == '' ) then return false end if ( strYesNo == 'Y' ) then return true elseif ( strYesNo == 'N') then return false end return false end -- 字符串为空(无效的一个字符串参数) function lua.StrIsEmpty( strValue ) if ( strValue == '' or strValue == nil or type( strValue ) ~= "string" ) then return true else return false end end -- 字符减1 function lua.DecrementChar(char) local ascii = string.byte(char) - 1 return string.char(ascii) end -- 字符加1 function lua.IncrementalChar(char) local ascii = string.byte(char) + 1 return string.char(ascii) end return lua