lua日期时间字符解析
下面介绍一种强大的日期时间字符解析方法,传入日期字符,返回数字类型的时间戳。由于日期格式 是多种多样的,日期字符的解析很难通过正则表达式来统一处理,例如:格式1是“2021-06-05 18:12:05 ”,而格式2是“2021/06/05”, 两种格式有差别,解析起来特别麻烦, 为此写了一个解析方法,基本到满足大部分的日期格式需求,如不满足可在此基础上修改。
解析字符需要符合以下格式:
2021-06-05 18:12:05 (符号"-"可以是除了冒号的任意符号)
2021/06/05 18:12:05
21-06-05 18:12:05
21/06/05 18:12:05
2021年06月05日
2021年06月05日 18:12:05
2012年03月08日 18小时30分钟50秒
210605 --即2021-06-05,时间默认是(00:00)
20210605
21-06-05
2021-06-05
20210605 18:12:00
210605 18:12:00
18:12, 18:12:05 --也可以时间格式,取当天的日期
实现思想:通过提取格式里的数字字符串列表,除去特殊字符,然后对数字字符串列表进行统一识别和处理。
代码如下:
function DateUtil.parseDateString(strTime)
local ret = 0
if not strTime then
print("parseDateString strTime is nil")
return ret
end
local textList = {} --数字字符列表
local symbolLen = 0 --特殊符号的长度
local isFirstMaoHao = false --首个字符是否冒号
local pStart = 1
local pFinal = 1
for i=1, #strTime do
local val = string.byte(strTime, i)
--截取数字的字符串列表,除去特殊字符
if val < 0x30 or val > 0x39 then
symbolLen = symbolLen + 1
if symbolLen == 1 and val == 0x3A then --是否冒号":"
isFirstMaoHao = true
end
pFinal = i
if pFinal > pStart then
local sub = string.sub(strTime, pStart, pFinal-1)
table.insert(textList, sub)
end
pStart = pFinal + 1
elseif i == #strTime then
--到结尾时,自动保存
if i >= pStart then
local sub = string.sub(strTime, pStart, i)
table.insert(textList, sub)
end
end
end
-- dump(textList, "textList")
local strYear, strMonth, strDay = "", "", ""
local strHour, strMin, strSec = "0", "0", "0"
local info = {year=0, month=0, day=0, hour=0, min=0, sec=0}
local textLen = #textList
if textLen == 0 then
print("parseDateString: not incluse digit", strTime)
return ret
end
local strFirst = textList[1]
if textLen == 1 then
if #strFirst == 8 then
--20210605 不带时间
strYear = string.sub(strFirst, 1, 4)
strMonth = string.sub(strFirst, 5, 6)
strDay = string.sub(strFirst, 7, 8)
elseif #strFirst == 6 then
--210605 不带时间
strYear = string.sub(strFirst, 1, 2)
strMonth = string.sub(strFirst, 3, 4)
strDay = string.sub(strFirst, 5, 6)
elseif #strFirst == 4 then
--2021 直接作为年份
strYear = strFirst
strMonth = "1"
strDay = "1"
else
print("parseDateString: wrong number of digits =", strTime)
return ret
end
else
if #strFirst == 6 then
--首个字符串是6个字符的日期 210605 18:12:00
strYear = string.sub(strFirst, 1, 2)
strMonth = string.sub(strFirst, 3, 4)
strDay = string.sub(strFirst, 5, 6)
if textLen >= 3 then
strHour = textList[2]
strMin = textList[3]
if textList[4] then
strSec = textList[4]
end
else
print("parseDateString: warning: first is 6bytes but textLen=", textLen)
end
elseif #strFirst == 8 then
--首个字符串是8个字符的日期 20210605 18:12:00
strYear = string.sub(strFirst, 1, 4)
strMonth = string.sub(strFirst, 5, 6)
strDay = string.sub(strFirst, 7, 8)
if textLen >= 3 then
strHour = textList[2]
strMin = textList[3]
if textList[4] then
strSec = textList[4]
end
else
print("parseDateString: warning: first is 8bytes but textLen=", textLen)
end
else
if textLen >= 5 then
-- 2021-06-05 18:12:00 2021-06-05 18:12
strYear = textList[1]
strMonth = textList[2]
strDay = textList[3]
strHour = textList[4]
strMin = textList[5]
strSec = textList[6] or "0"
elseif textLen >= 2 and textLen <= 4 then
if not isFirstMaoHao then
-- 21-06-05 2021-06-05
strYear = textList[1]
strMonth = textList[2]
strDay = textList[3] or "0"
else
-- 18:12 18:12:00 18:12:00.0
--首字符是冒号,取当前是时间
local tab = os.date("*t", os.time())
strYear = tostring(tab.year)
strMonth = tostring(tab.month)
strDay = tostring(tab.day)
strHour = textList[1]
strMin = textList[2]
strSec = textList[3] or "0"
end
else
print("parseDateString: format err 2")
return ret
end
end
end
if #strYear > 0 then
--解析字符,检查格式
info.year = tonumber(strYear)
if not info.year then
print("parse err year=", strYear)
return ret
end
info.month = tonumber(strMonth)
if (not info.month) or info.month <= 0 or info.month > 12 then
print("parse err month=", strMonth)
return ret
end
info.day = tonumber(strDay)
if (not info.day) or info.day <= 0 or info.day > 31 then
print("parse err day=", strDay)
return ret
end
info.hour = tonumber(strHour)
if (not info.hour) or info.hour < 0 or info.hour > 24 then
print("parse err hour=", strHour)
return ret
end
info.min = tonumber(strMin)
if (not info.min) or info.min < 0 or info.min > 60 then
print("parse err min=", strMin)
return ret
end
info.sec = tonumber(strSec)
if (not info.sec) or info.sec < 0 or info.sec > 60 then
print("parse err sec=", strSec)
return ret
end
--两位年份,补到2000年
if info.year < 100 then
info.year = info.year + 2000
end
--转化为时间戳
ret = os.time(info) or 0;
-- dump(info, "parseDateString: info")
-- print("parseDateString: ret=", ret)
end
return ret
end
测试代码
function DateUtil.test()
local time = DateUtil.parseDateString("2020/09/01 18:30:56")
print("parseDateString time=", os.date("%Y-%m-%d %H:%M:%S", time))
end