游戏开发中的时间格式化显示之lua时间格式化显示

需求与场景分析

在游戏前端开发中,我经常遇到把时间格式化成多种格式在不同UI上显示的需求。又或者是不同功能需要显示不同格式的时间。最多的就是对服务器返回的一个剩余时间秒数进行倒计时的显示,例如活动剩余时间、某些操作的CD时间等。
下面列举一些常要用到的显示格式:

  1. 12:05:03
  2. 12小时05分钟03秒
  3. 12时05分03秒
  4. 剩余0天12时5分5秒
  5. 50分05秒 (当小时小于0时不显示)
    就先列举5个,在同一个游戏项目中可能在不同场景,不同界面就需要显示不一样的时间格式,
    我们该如何处理这种情况呢?
    我常常看到一些处理方式是,在一个工具类里定义多个格式化函数,需要哪个格式就调用哪个函数。
    例如:
DateTimeUtils.FormatTime1  
DateTimeUtils.FormatTime2 
DateTimeUtils.FormatTime3 

这种方式虽然可以解决问题,但是会发觉后面格式化函数越来越多,里面有大量冗余的代码。
所以我就想可不可以用一个方法就能支持多种格式的呢?
通过分析时间格式化的需求,其实不同也就是非数字部分的内容,所以我就想着可以通过正则和字符串分割的方式写了一个方法能满足大多数的格式化需求.
例如:

  • 传入 DateTimeUtils.Format(“剩余dd天hh时m分s秒”,sec) 返回 剩余0天12时05分03秒
  • 传入 DateTimeUtils.Format(“hh:mm:ss”,sec) 返回 12:05:03

代码实现

定义支持的格式,‘日时分秒’分别对应=>dhms

local fmtSecInfo = {}
fmtSecInfo["d"] = 86400 -- 1天的秒数
fmtSecInfo["h"] = 3600 --1小时的秒数
fmtSecInfo["m"] = 60 --一分钟的秒数
fmtSecInfo["s"] = 0

分析传入的格式

local sec = 0 + 3600*3 + 60*3 + 26  --0天3小时3分26秒
local fmt = "剩余dd天hh时mm分s秒"
local startIdx = 1
local parttern = "%l+" --正则匹配1个或多个小写字母
local i,j = string.find( fmt,parttern,startIdx)
local fmtChar = string.match(fmt,parttern,startIdx) --从左到右得到第一个格式字符

截取格式前面的字符

local retFmt = string.sub(fmt,1,i-1)

到这里完成了第一个格式的提取工作,接下来就是根据格式字符串转换秒数到具体的时间格式,然后执行循环处理即可。

local useShort = true --是否为0的不显示 例如 剩余dd天hh时m分s秒 当天数为0时 显示成 剩余hh时m分s秒 
while j and fmtChar do
    print("while find i=",i,"j=",j,"fmtChar=",fmtChar)
    startIdx = j + 1
    local k,m = string.find( fmt,parttern,startIdx)
    local nextStart = k and k - 1 or #fmt
    local f = string.sub(fmtChar,1,1)
    local fmtSec  = fmtSecInfo[f] --获取该格式的秒数 例如 h=3600 一小时的描述
    if not fmtSec then
        return "时间格式="..fmt.." 无效"
    end

    local val
    if fmtSec > 0 then
        val = math.floor(sec/fmtSec) --计算具体数值
        sec = sec%fmtSec
    else
        val = sec 
    end
    
    if val > 0 or not useShort then
        local valStr = tostring(val)
        if #fmtChar==2 and val < 10 then --传入的格式是2个字符的 显示的数字不足10也是2位数
            valStr = "0"..val
        end
        --截取拼接非格式部分的内容
        local tempFmtStr = string.sub(fmt,i,nextStart)
        retFmt = retFmt..string.gsub(tempFmtStr,parttern,valStr)
    end
    fmtChar = string.match(fmt,parttern,startIdx)

    i,j= k,m
end

至此完成了格式化的定义,封装成函数的完整代码

--通用的格式化时间显示
---@param sec integer 剩余秒数
---@param fmt string 时间显示格式,日时分秒 -> dhms (如果是双字母表示小于10的显示成01,例如:hh 1小时 就显示成 01小时 ) 例如: 剩余dd天hh时m分s秒,hh:mm:ss
---@param useShort boolean 是否为0的不显示 例如 剩余dd天hh时m分s秒 当天数为0时 显示成 剩余hh时m分s秒
---@examples 调用样例: DateTimeUtils.Format(sec,"hh:mm:ss") 返回 06:05:01 ; 
function DateTimeUtils.Format(sec,fmt,useShort)
    fmt = string.lower(fmt)
    local fmtSecInfo = {}
    fmtSecInfo["d"] = 86400 -- 1天的秒数
    fmtSecInfo["h"] = 3600 --1小时的秒数
    fmtSecInfo["m"] = 60 --一分钟的秒数
    fmtSecInfo["s"] = 0

    local startIdx = 1
    local parttern = "%l+" 
    local i,j = string.find( fmt,parttern,startIdx)
    local fmtChar = string.match(fmt,parttern,startIdx)
    local retFmt = string.sub(fmt,1,i-1)
    while j and fmtChar do
        print("while find i=",i,"j=",j,"fmtChar=",fmtChar)
        startIdx = j + 1
        local k,m = string.find( fmt,parttern,startIdx)
        local nextStart = k and k - 1 or #fmt
        local f = string.sub(fmtChar,1,1)
        local fmtSec  = fmtSecInfo[f]
        if not fmtSec then
            return "时间格式="..fmt.." 无效"
        end

        local val
        if fmtSec > 0 then
            val = math.floor(sec/fmtSec)
            sec = sec%fmtSec
        else
            val = sec 
        end
        
        if val > 0 or not useShort then
            local valStr = tostring(val)
            if #fmtChar==2 and val < 10 then
                valStr = "0"..val
            end
            local tempFmtStr = string.sub(fmt,i,nextStart)
            retFmt = retFmt..string.gsub(tempFmtStr,parttern,valStr)
        end
        fmtChar = string.match(fmt,parttern,startIdx)

        i,j= k,m
    end
    return retFmt
end

测试几个格式看看结果:
各个格式测试
看看输出的结果:
对应的输出结果
完成!如果喜欢欢迎收藏转发,如果有错误可以指出。谢谢!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值