在 Lua 脚本里,时间戳通常是最原始也最难直接阅读的数据形态。以 Wireshark 的 Lua 插件为例,抓包时间如果直接展示为整型值,查看和排错都会变得不直观;本文就围绕这个实际问题,拆解如何用 os.date(format, stampTime) 把时间戳转成可读日期,并说明格式字符串该怎么选,方便你按业务需要快速改造输出结果。
为什么要把时间戳转成日期
原始时间戳更适合程序计算,但不适合直接给用户或测试人员阅读。在自定义协议解析、日志展示、抓包结果查看这类场景里,展示成标准日期时间通常更容易判断事件发生顺序,也方便和其他系统日志做对照。
本文对应的使用环境是 Wireshark 的 Lua 脚本插件。需求本身并不复杂:从数据包字段中取出时间戳,再把它显示成类似 2021-09-26 16:26:32 的形式。
一行代码完成转换
如果你已经拿到了整型时间戳,那么真正完成转换的核心就是下面这句:

-- 定义将时间戳转换为日期式时间的方法
function stamp2date(offset)
local stamp_time = tvb(offset,4) -- 这条代码你可以理解为在我的应用场景里获取时间戳的一行代码,看不懂没关系,是wireshark的lua脚本专用接口
return os.date("%Y-%m-%d %H:%M:S",stamp_time) -- 本文核心,使用os.date(format,stampTime)方法将时间戳转换为指定格式的日期,本例中将返回一个2021-09-26 16:26:32格式的数据
end
这段代码可以分成两步理解:
先取出时间戳
tvb(offset,4) 是 Wireshark Lua 脚本里的专用接口,用来从当前解析数据中取出时间字段。它属于具体场景代码,即使你不在 Wireshark 里开发,也不影响理解本文后面的转换逻辑。
再用 os.date 转成日期字符串
os.date(format, stampTime) 是 Lua 自带方法,作用就是把时间戳格式化为指定样式的日期字符串。只要时间戳值正确,最终输出成什么样,主要由 format 这个格式串决定。
按本文给出的写法,它希望返回的是类似 2021-09-26 16:26:32 这样的结果,也就是“年-月-日 时:分:秒”的常见展示方式。
os.date 的两个参数怎么理解
os.date(format, stampTime) 只涉及两个参数,但分别决定了“显示成什么格式”和“转换哪一个时间戳”。

format:控制日期长什么样
format 是自定义日期格式字符串。你可以把它理解为模板:哪些位置显示年、月、日、小时、分钟、秒,都由格式符拼出来。
原文中列出的常用写法如下,保留后更方便直接查:
| 字符 | 意义 | 示例 |
|---|---|---|
| os.date("%a") | abbreviated weekday name | Sun |
| os.date("%A") | full weekday name | Sunday |
| os.date("%b") | abbreviated month name | Jul |
| os.date("%B") | full month name | July |
| os.date("%c") | date and time | 07/27/14 17:42:09 |
| os.date("%d") | day of the month | 27 |
| os.date("%H") | hour, using a 24-hour clock (23) [00-23] | 17 |
| os.date("%I") | hour, using a 12-hour clock (11) [01-12] | 5 |
| os.date("%M") | minute (48) [00-59] | 42 |
| os.date("%m") | month (09) [01-12] | 7 |
| os.date("%p") | either "am" or "pm" (pm) | PM |
| os.date("%S") | second (10) [00-61] | 9 |
| os.date("%w") | weekday (3) [0-6 = Sunday-Saturday] | 0 |
| os.date("%x") | date | 07/27/14 |
| os.date("%X") | time(e.g., 23:48:10) | 17:42:09 |
| os.date("%Y") | full year (2016) | 2016 |
| os.date("%y") | two-digit year (98) [00-99] | 16 |
如果只是常规展示,最常用的通常是下面几个:
%Y:四位年份%m:两位月份%d:两位日期%H:24 小时制小时%M:分钟%S:秒
例如:
os.date("%Y-%m-%d %H:%M:%S", stampTime)
这就是最常见、也最适合日志和抓包结果展示的一种格式。
stampTime:待转换的时间戳
stampTime 就是要被转换的整型时间戳数据。只要这个值本身正确,os.date 就会按你指定的模板输出对应日期。
换句话说,os.date 不负责“从哪里取时间戳”,它负责的是“把已有时间戳排版成可读字符串”。这也是为什么 Wireshark 场景中的 tvb(offset,4) 和 os.date(...) 可以拆开理解。
在实际项目里怎么改最省事
如果你的目标只是把界面里的原始时间字段改得更易读,通常不需要自己手写复杂日期逻辑,直接调整 format 就够了。
比如:
- 只显示日期:
os.date("%Y-%m-%d", stampTime) - 只显示时间:
os.date("%H:%M:%S", stampTime) - 显示完整日期时间:
os.date("%Y-%m-%d %H:%M:%S", stampTime)
对于协议解析、日志查看、问题定位这些偏工程化的场景,推荐优先使用完整日期时间格式。它可读性高,也方便和其他系统输出做逐条比对。
总的来说,Lua 中把时间戳展示为日期并不复杂,关键就是记住 os.date(format, stampTime) 这个方法:前者定显示格式,后者传入时间戳。一旦把这两个参数分清,后续无论是在 Wireshark Lua 插件里,还是在普通 Lua 脚本中处理时间展示,基本都能直接套用。





