我如何将Unix时间转换为可读的值?

高频处理时间问题

在处理时间值时,程序中的一种常见方法是将其转换为线性刻度表示。无法将"2005年1月17日下午5:37"这样的日期存储为变量,并期望能够进行任何操作。

因此,在合格的程序中,时间值通常以时间戳的形式表示,即与特定时点之间的秒数。这被称为时代时间戳,如果以1970年1月1日的UTC午夜为起始点,则被称为Unix时间戳,因为这是Unix系统存储所有时间(如文件修改时间)的方式。

unix下处理时间戳

处理Unix时间戳的最常用工具是Unix标准中的date命令。GNU date和后来的BSD date提供了一个%s选项,用于以Unix时间戳格式生成输出。

以下是一些用法示例:

# GNU/BSD date
date +%s       # 打印当前时间的Unix格式,例如1164128484
date -u +%s    # 从UTC开始的秒数。这会清除本地夏令时或本地时间修正。

在脚本中计算两个事件之间的时间间隔时,通常会使用以下示例代码:

# POSIX shell,带有GNU/BSD date
start=$(date -u +%s)
...
end=$(date -u +%s)
echo "操作耗时$(($end - $start))秒。"

要将Unix时间戳转换为可读的日期和时间格式,我们可以使用特定的date命令:

# GNU date
date -u -d "1970-01-01" +"%s 秒"      # 打印"0秒"
date -u -d "1970-01-01" +"%D %T"           # 打印"01/01/70 00:00:00"

date -u -d "1970-01-01 14415 秒" +"%D %T"
date -u -d @14415 +"%D %T"   # 替代的表示法
            # 打印"01/01/70 04:00:15",即比起时代时间戳晚4小时15秒。
date -u -d "1970-01-01 14415 秒 - 3605 秒" +"%D %T"
            # 打印"01/01/70 03:00:10",即比起时代时间戳晚4小时15秒、早2小时5秒。

因此,我们可以使用下面的单个命令来转换Unix时间戳(假设start和end是以秒为单位的变量):

# 假设start为"1418347200",end为"1418350815"(举例):
date -u -d "1970-01-01 $end 秒 - $start 秒" +"%T"

# 打印通常(人类可读)时间格式的时间差:
01:00:15
# 输出格式可以根据需要进行调整。

请注意,此方法仅适用于少于24小时的时间间隔。对于较长的时间间隔,需要进行额外的数学计算。

如果您使用的是较新版本的bash(4.2 及更高版本),可以使用printf命令的%(fmt)T选项进行时间转换:

# 将当前时代时间存储在"$start"中(仅限BSD/GNU)
printf -v start '%(%s)T' -1

# 在人类可读格式(可移植)中打印保存的时代时间:
printf '%(%Y-%m-%d %H:%M:%S)T\n' "$start"

如果您没有可用的GNU date或较新版本的bash,可以使用Perl命令:

perl -le "print scalar localtime 1164128484"
# 打印"Tue Nov 21 12:01:24 2006"

我在这些示例中使用了双引号,以便将时间常量替换为变量引用。有关如何更改输出格式的详细信息,请参阅date(1)和Perl的文档。

对于使用较新版本的Tcl(8.5 及更高版本)的用户,可以使用其date和clock函数进行日期和时钟操作:

echo 'puts [clock format [clock scan "today"]]' | tclsh
# 打印今天的日期(可以通过参数调整“clock format”格式)。

echo 'puts [clock format [clock scan "fortnight"]]' | tclsh
# 打印两周后的日期。

echo 'puts [clock format [clock scan "5 years + 6 months ago"]]' | tclsh
# 五年半前的日期,考虑闰日和夏令时。

要计算自"YYYY MM DD HH MM SS"以来经过的秒数,GNU awk是一个方便的工具:

echo "2008 02 27 18 50 23" | awk '{print systime() - mktime($0)}'
# 使用systime()返回当前时间的时代格式
# 使用mktime()在输入字符串上返回输入字符串的时代时间
# 这些都是GNU awk的扩展;mawk也可能适用。

为了使其更具人类可读性,可以使用GNU awk的strftime()。格式字符串与GNU date类似。

echo "YYYY MM DD HH MM SS" | gawk '{print strftime("%M分钟,%S秒",systime() - mktime($0))}'
# gawk特定的strftime()函数将差值转换为人类可读格式

学习更多shell有用知识点

如果您想了解并学习更多shell的更多编程技巧和编程最佳实践,可以关注我正在编写的《shell脚本编程最佳实践》里面包含了一线互联网大厂最佳实践经验总结。

原文链接:,转发请注明来源!