Shell中如何将绝对日期转换为带时间差标注的相对日期?
Shell环境下带相对时间差的日期格式化实现
核心依赖为GNU date,绝大多数Linux发行版默认预装;macOS等BSD系统需先通过brew install coreutils安装,后续命令替换为gdate即可使用。
实现逻辑
整体分四步处理两类输入:
- 统一输入格式:自动识别输入类型,将ISO日期字符串、纯数字Unix时间戳都转换为秒级Unix时间戳,方便后续计算
- ISO格式(如
2022-06-18T11:03:40+0800):用date -d "输入字符串" +%s直接转换 - 纯数字时间戳(如
1655107420):直接读取为时间戳即可
- ISO格式(如
- 计算时间差:取当前系统时间的秒级时间戳,和目标时间戳做差,根据差值正负判断是“前”还是“后”
- 生成相对时间文本:按差值大小匹配对应时间粒度,生成类似“3分钟前”的标注,可按需调整粒度规则
- 格式化绝对时间:将目标时间戳按要求的
星期, 月份 日, 年 at 时:分:秒格式输出,最后拼接相对时间标注
可直接复用的脚本代码
# 日期格式化函数,传入ISO日期字符串或Unix时间戳即可输出目标格式 format_date() { input="$1" # 识别输入类型,转换为目标时间戳 if [[ "$input" =~ ^[0-9]+$ ]]; then target_ts="$input" else target_ts=$(date -d "$input" +%s) || { echo "日期格式解析失败"; return 1; } fi current_ts=$(date +%s) diff=$((current_ts - target_ts)) tense="前" # 处理未来时间的情况 if [ $diff -lt 0 ]; then tense="后" diff=$(( -diff )) fi # 计算相对时间文本,可自行调整粒度规则 if [ $diff -lt 60 ]; then rel="刚刚" elif [ $diff -lt 3600 ]; then rel="$((diff / 60))分钟${tense}" elif [ $diff -lt 86400 ]; then rel="$((diff / 3600))小时${tense}" else rel="$((diff / 86400))天${tense}" fi # 格式化绝对日期部分,需要英文星期/月份保持默认locale即可,需要中文则切换为zh_CN.UTF-8 abs_part=$(date -d "@$target_ts" +"%A, %B %d, %Y at %H:%M:%S") echo "${abs_part} (${rel})" }
使用示例
# 传入ISO格式日期 format_date "2022-06-18T11:03:40+0800" # 传入Unix时间戳 format_date 1655107420
输出效果和需求一致:
Saturday, June 18, 2022 at 11:03:40 (2 years ago) Saturday, June 18, 2022 at 11:23:40 (2 years ago)
注意事项
- 若需要输出中文的星期、月份名称,执行date命令前加
LC_TIME=zh_CN.UTF-8前缀即可 - 若需要更细/更粗的相对时间粒度(比如显示“N周前”“N个月前”),直接修改相对时间计算部分的判断分支即可
- macOS用户记得把脚本中所有
date替换为gdate,否则会出现参数不兼容报错
内容的提问来源于stack exchange,提问作者8c6b5df0d16ade6c
相关产品推荐
相关产品推荐

