340

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

ts2date 1267619929

echo 1267619929 | ts2date

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

4

17 回答 17

646

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

date -d @1267619929
于 2010-03-03T12:47:51.077 回答
203
date -r <number>

在 Mac OS X 上为我工作。

于 2012-10-26T13:49:15.570 回答
29

此版本类似于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
于 2010-03-03T14:11:33.970 回答
18

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

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

或者

$ date -ud @1267619929
于 2010-03-03T12:51:33.477 回答
11

您可以像这样从时间戳中获取格式化日期

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"
于 2019-04-19T08:28:26.037 回答
10

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

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

示例用法:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
于 2010-03-03T12:45:09.453 回答
9

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

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

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

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


现在,如果您想要一个接受参数的脚本,并且如果没有提供,则读取标准输入,您可以继续:

#!/bin/bash

if (($#)); then
    printf '%(%c)T\n' "$@"
else
    while read -r line; do
        printf '%(%c)T\n' "$line"
    done
fi
于 2017-09-13T17:27:57.503 回答
9

我使用这个跨平台的单线:

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

它应该适用于 macOS 和流行的 Linux 发行版的现代版本。

于 2019-12-16T07:31:49.613 回答
6

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

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
于 2014-04-17T07:24:24.653 回答
6

在 OSX 或 BSD 中,有一个等效的-r标志,显然需要一个 unix 时间戳。这是一个运行四次 date 的示例:第一个 date 一次,显示它是什么;一个用于转换为带有 的unix 时间戳%s,最后一个用于-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
于 2017-10-24T21:46:46.340 回答
3

我自己编写了一个脚本:

#!/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); }'
于 2010-03-03T12:42:50.713 回答
3

在这个答案中,我复制了 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
于 2014-09-25T23:08:14.307 回答
2

一些例子:

$日期
2016 年 3 月 22 日星期二 16:47:06 CST

$ date -d "2016 年 3 月 22 日星期二 16:47:06 CST" "+%s"
1458636426

$ 日期 +%s
1458636453

$日期-d@1458636426
2016 年 3 月 22 日星期二 16:47:06 CST

$ 日期 --date='@1458636426'
2016 年 3 月 22 日星期二 16:47:06 CST


于 2016-03-22T08:58:33.750 回答
0

虽然不是纯 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"}
于 2019-11-07T13:47:00.567 回答
0

我必须在我的 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
于 2020-12-14T13:45:16.423 回答
0

如果您希望一次格式化多个时间戳,我编写了一个名为datefmt的 C 实用程序,用于格式化文本流中的时间戳:

假设我们有一些包含 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

于 2021-12-10T16:33:13.780 回答
-9

在 PHP 中

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
于 2010-03-03T12:43:35.940 回答