如何在Bash中将时间戳转换为日期?

我需要一个shell命令或脚本,将Unix时间戳转换为日期。输入可以来自第一个参数,也可以来自stdin,允许以下使用模式:

ts2date 1267619929

而且

echo 1267619929 | ts2date

这两个命令都应该输出“Wed Mar 3 13:38:49 2010”。

368631 次浏览

我自己写了一个脚本:

#!/bin/bash
LANG=C
if [ -z "$1" ]; then
if [  "$(tty)" = "not a tty" ]; then
p=`cat`;
else
echo "No timestamp given."
exit
fi
else
p=$1
fi
echo $p | gawk '{ print strftime("%c", $0); }'

在PHP中

$unix_time = 1256571985;


echo date("Y-m-d H:i:s",$unix_time)

你可以使用这个简单的awk脚本:

#!/bin/gawk -f
{ print strftime("%c", $0); }

示例用法:

$ echo '1098181096' | ./a.awk
Tue 19 Oct 2004 03:18:16 AM PDT
$

GNU Coreutils >= 5.3.0的系统上,例如Linux,你可以使用:

date -d @1267619929

例如,你可以使用GNU日期,

$ sec=1267619929
$ date -d "UTC 1970-01-01 $sec secs"

$ date -ud @1267619929

这个版本类似于chiborg的 回答,但它消除了外部ttycat的需要。它使用date,但也可以很容易地使用gawk。你可以改变shebang并将双方括号替换为单方括号,这也将运行在sh中。

#!/bin/bash
LANG=C
if [[ -z "$1" ]]
then
if [[ -p /dev/stdin ]]    # input from a pipe
then
read -r p
else
echo "No timestamp given." >&2
exit
fi
else
p=$1
fi
date -d "@$p" +%c
date -r <number>

可以在macosx上使用。

我在转换日志文件或监控它们时使用这个:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'

在这个答案中,我复制了Dennis Williamson的答案,并对其稍加修改,以便在将许多时间戳的列输出到脚本时大幅提高速度。例如,在我的机器上,用xargs -n1将1000个时间戳传送到原始脚本需要6.929秒,而修改后的版本需要0.027秒:

#!/bin/bash
LANG=C
if [[ -z "$1" ]]
then
if [[ -p /dev/stdin ]]    # input from a pipe
then
cat - | gawk '{ print strftime("%c", $1); }'
else
echo "No timestamp given." >&2
exit
fi
else
date -d @$1 +%c
fi

一些例子:

$ date
Tue Mar 22 16:47:06 CST 2016


$ date -d "Tue Mar 22 16:47:06 CST 2016" "+%s"
1458636426


$ date +%s
1458636453


$ date -d @1458636426
Tue Mar 22 16:47:06 CST 2016


$ date --date='@1458636426'
Tue Mar 22 16:47:06 CST 2016




从Bash 4.2开始,你可以使用printf%(datefmt)T格式:

$ printf '%(%c)T\n' 1267619929
Wed 03 Mar 2010 01:38:49 PM CET

这很好,因为它是一个内置的外壳。datefmt的格式是strftime(3)接受的字符串(参见man 3 strftime)。这里%c是:

%c当前的首选日期和时间表示 语言环境。< / p >


现在,如果你想要一个接受参数的脚本,如果没有提供参数,则读取stdin,你可以继续执行:

#!/bin/bash


if (($#)); then
printf '%(%c)T\n' "$@"
else
while read -r line; do
printf '%(%c)T\n' "$line"
done
fi

在OSX或BSD中,有一个等效的-r标志,它显然接受unix时间戳。下面是一个运行date四次的示例:一次是第一次约会,以显示它是什么;一个是使用%s转换为unix时间戳,最后一个是使用-r%s提供的内容转换回字符串。

$  date; date +%s; date -r `date +%s`
Tue Oct 24 16:27:42 CDT 2017
1508880462
Tue Oct 24 16:27:42 CDT 2017

至少在我的机器上还能用。

$ uname -a
Darwin XXX-XXXXXXXX 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64

你可以像这样从时间戳中得到格式化的日期

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"

虽然不是纯bash,但下面的脚本将使用perl将字符串中长度为13的时间戳转换为本地时区中的等效日期

timestamp_to_date.sh

#!/usr/bin/env bash
IT=$(cat /dev/stdin)
re='(.*)([0-9]{13})(.*)'
while [[ $IT =~ $re ]]; do
TIMESTAMP=${BASH_REMATCH[2]}
AS_DATE=$(echo "$TIMESTAMP" | perl -pe 's/([\d]{10})([\d]{3})/localtime $1/eg;')
IT="${IT/$TIMESTAMP/$AS_DATE}"
done
echo "$IT"

输入

{"timestamp":"1573121629939","level":"DEBUG","thread":"http-nio-15372-exec-3","logger":"org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor"}

输出

$ cat input | timestamp_to_date.sh


{"timestamp":"Thu Nov  7 06:13:49 2019","level":"DEBUG","thread":"http-nio-15372-exec-3","logger":"org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor"}

我使用这个跨平台的一行代码:

date -d @1267619929 2>/dev/null || date -r 1267619929

它应该可以在macOS和流行的Linux发行版的现代版本中运行。

我必须在bash历史记录中转换内联的时间戳,以便对我有意义。

也许下面来自我如何用sed, awk或这样的shell命令的输出替换子字符串?的答案对其他读者来说也会很有趣。 原始sed内联代码的荣誉归@Gabriel.

cat ~/.bash_history | sed "s/^#\([0-9]\+\)$/echo -n '#'; date -u --d @\1 '\+\%Y-\%m-\%d \%T'/e" | less

如果你想一次格式化许多时间戳,我写了一个名为datefmt的C util,它在文本流中格式化时间戳:

假设我们有一些包含unix时间戳的日志:

$ cat logs.txt


EVENTS  1638499687   blahblah log1
EVENTS  1638499717   blahblah log2

我们可以将该日志管道到datefmt中,将这些时间戳转换为人类可读的日期:

$ <logs.txt datefmt


EVENTS  2021-12-02 18:48   blahblah log1
EVENTS  2021-12-02 18:48   blahblah log2

当然,你也可以自定义格式:

$ <logs.txt datefmt "DATE:'%m-%d %R'"


EVENTS  DATE:'12-02 18:48'   blahblah log1
EVENTS  DATE:'12-02 18:48'   blahblah log2

我已经在NixOS中打包了它,希望它很快就会渗透到其他发行版中,但现在你需要下载tarball并使用make构建它