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


270

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

ts2date 1267619929

echo 1267619929 | ts2date

这两个命令都应输出“ 2010年3月3日星期三13:38:49”。

Answers:


531

在普通Linux发行版的更高版本上,您可以使用:

date -d @1267619929

5
单线:date -d @$(date -u +%s)
Mike Atlas,

26
有什么@用 我在GNU手册页中根本看不到。
Mark E. Haase'2

13
@mehaase -男子页指出,日线太复杂的联机帮助加以记录,所以它在信息说明:信息“(的coreutils)日期调用”
MByD

10
brew install coreutils; gdate -d @1267619929
马克·福克斯

2
info 'Date input formats' 将您直接带到date的formatting info节点,并带有相关的Robert Grudin引号,然后是格式说明符菜单。
麦克(Mike)

165
date -r <number>

在Mac OS X上对我有效。


5
是的,但是它不能处理几分之一秒。
mgold 2013年

1
而且令人困惑,因为它不能在大多数linux系统上以这种方式工作,因为:freddy @ hades〜%date --help | grep--r -r,--reference = FILE显示FILE的最后修改时间
frank42 '17

1
尽管对这个答案的评论是正确的,但这并不是拉法的错,也不会减少他的答案。
迈克,

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

+1:非常完整的答案,我认为约会要比gawk快。
布鲁诺·布兰特

@Bruno,您怎么知道约会比gawk快?
ghostdog74 2010年

3
@ Bruno,@ ghostdog74:在我的系统上,gawk(大约)比仅包含或将输出重定向到date的定时for循环快15%。gawk 'BEGIN { print strftime("%c", 1256571985); }'date -d '@1256571985' +%c/dev/null
暂停,直到另行通知。

1
对我来说,日期比gawk快一点(5%)(mac osx 10.9.2,日期8.23,gawk 4.1.1),但是(g)awk的真正优势是可以接受包含多个时间戳列的管道(请参见我的回答如下),这使脚本(例如250x)的运行速度达到了1000个时间戳。
webb 2014年

3
请注意,我的答案符合问题中所述操作程序的要求,但现在不接受。
暂停,直到另行通知。

17

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

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

要么

$ date -ud @1267619929

10

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

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

用法示例:

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

这不适合第一次使用-有时我不想回显TS并改用参数。
Chiborg'3

在某些较旧的busybox版本上,date -s @它无法正常工作,awk仍然可以!没有标准输入的示例也将有所帮助。
维克托·谢尔琴科

8

从Bash 4.2开始,您可以使用printf%(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 当前语言环境的首选日期和时间表示形式。


现在,如果您想要一个接受参数的脚本,并且如果未提供参数,则读取stdin,则可以执行以下操作:

#!/bin/bash

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

6

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

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

正是我想要的,可以缩短为awk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue

5

在OSX或BSD中,有一个等效-r标志,显然需要一个unix时间戳。这是一个运行日期四次的示例:一次是第一次显示日期,另一次是显示日期。一个用于使用转换为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

如果您已经有一个时间戳记值,而只需要查找等效的日期,则在OS X中,您可以在命令行中键入:date -r 1509453417
Noel

1
确实如此。如果您看我的回答,我实际上是在证明这一点。
丹尼尔·法雷尔

5

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

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

周围的其他方式:日期-ud “@ 1585667718” + '%Y-%间%d%H:%M:%S'
AndiAna

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); }'

1
您的问题标签包括“ bash”,但您的shebang说“ sh”。
暂停,直到另行通知。

3

在此答案中,我复制了丹尼斯·威廉姆森的答案,并对其进行了稍微的修改,以在将包含多个时间戳记的列传递到脚本时大大提高速度。例如,在我的计算机上使用xargs -n1将1000个时间戳传递到原始脚本需要6.929s,而使用此修改后的版本需要0.027s:

#!/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

2

一些例子:

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

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

$日期+%s
1458636453

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

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



2

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

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

它既可以在macOS上也可以在普通Linux发行版的更高版本中使用。


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"}

-8

在PHP中

$unix_time = 1256571985;

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

5
很好,但是我只是想使用bash。
Chiborg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.