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

发布于 2024-08-24 05:18:27 字数 219 浏览 6 评论 0原文

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

ts2date 1267619929

并且

echo 1267619929 | ts2date

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

I need a shell command or script that converts a Unix timestamp to a date. The input can come either from the first parameter or from stdin, allowing for the following usage patterns:

ts2date 1267619929

and

echo 1267619929 | ts2date

Both commands should output "Wed Mar 3 13:38:49 2010".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

离鸿 2024-08-31 05:18:27

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

date -d @1267619929

On systems with GNU Coreutils >= 5.3.0, e.g. Linux you can use:

date -d @1267619929
千秋岁 2024-08-31 05:18:27
date -r <number>

我在 Mac OS X 上工作。

date -r <number>

works for me on Mac OS X.

蝶…霜飞 2024-08-31 05:18:27

此版本类似于 chiborg 答案,但它消除了对外部 tty< 的需要/code> 和 cat。它使用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

This version is similar to chiborg's answer, but it eliminates the need for the external tty and cat. It uses date, but could just as easily use gawk. You can change the shebang and replace the double square brackets with single ones and this will also run in 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
旧伤慢歌 2024-08-31 05:18:27

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

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

或者

$ date -ud @1267619929

You can use GNU date, for example,

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

or

$ date -ud @1267619929
享受孤独 2024-08-31 05:18:27

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

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

You can get formatted date from timestamp like this

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"
清醇 2024-08-31 05:18:27

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

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

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

I use this cross-platform one-liner:

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

It should work both in macOS and modern versions of popular Linux distributions.

清欢 2024-08-31 05:18:27

从 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

Since Bash 4.2 you can use printf's %(datefmt)T format:

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

That's nice, because it's a shell builtin. The format for datefmt is a string accepted by strftime(3) (see man 3 strftime). Here %c is:

%c The preferred date and time representation for the current
locale.


Now if you want a script that accepts an argument and, if none is provided, reads stdin, you can proceed as:

#!/bin/bash

if (($#)); then
    printf '%(%c)T\n' "$@"
else
    while read -r line; do
        printf '%(%c)T\n' "$line"
    done
fi
在你怀里撒娇 2024-08-31 05:18:27

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

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

示例用法:

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

You can use this simple awk script:

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

Sample usage:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
°如果伤别离去 2024-08-31 05:18:27

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

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

I use this when converting log files or monitoring them:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
饭团 2024-08-31 05:18:27

在 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

In OSX, or BSD, there's an equivalent -r flag which apparently takes a unix timestamp. Here's an example that runs date four times: once for the first date, to show what it is; one for the conversion to unix timestamp with %s, and finally, one which, with -r, converts what %s provides back to a string.

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

At least, seems to work on my machine.

$ 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
疯了 2024-08-31 05:18:27

我自己编写了一个脚本来执行此操作:

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

I have written a script that does this myself:

#!/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); }'
蒲公英的约定 2024-08-31 05:18:27

在这个答案中,我复制了 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

In this answer I copy Dennis Williamson's answer and modify it slightly to allow a vast speed increase when piping a column of many timestamps to the script. For example, piping 1000 timestamps to the original script with xargs -n1 on my machine took 6.929s as opposed to 0.027s with this modified version:

#!/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
浮生未歇 2024-08-31 05:18:27

一些例子:

$ 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


some example:

$ 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


臻嫒无言 2024-08-31 05:18:27

我喜欢以前针对特殊情况的解决方案:printf '%(%c)T\n' $timestamp(如果您有 Bash>=4.2)、date -d @$timestamp code> (如果您有 GNU Coreutils >= 5.3.0),date -r $timestamp (如果您使用的是 BSD/MacOS),但我需要一些更便携的东西,所以我选择了 jq 我到处都可以帮助处理 JSON:

jq 'todate' <<< $timestamp

可以在函数中使用它来获得所需的效果:

ts2date() { [[ -n "$1" ]] && { jq 'todate' <<< $1 ; true;} || jq 'todate' ; }

I like the previous solutions for special cases: printf '%(%c)T\n' $timestamp (if you have Bash>=4.2), date -d @$timestamp (if you have GNU Coreutils >= 5.3.0), date -r $timestamp (if you are on BSD/MacOS), but I needed something more portable and I opted for jq that I have everywhere to help with JSON:

jq 'todate' <<< $timestamp

Which could be used in a function to obtain the desired effect:

ts2date() { [[ -n "$1" ]] && { jq 'todate' <<< $1 ; true;} || jq 'todate' ; }
演多会厌 2024-08-31 05:18:27

将字符串中长度为 13 的时间戳转换为本地时区中的等效日期

虽然不是纯 bash,但以下脚本将使用 perl 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"}

While not pure bash, the following script will convert timestamps of length 13 in a string to their equivalent date in your local timezone using perl

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"

input

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

output

$ 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"}
凡尘雨 2024-08-31 05:18:27

我必须在 bash 历史记录中内联转换时间戳才能对我有意义。

也许以下内容来自对 如何用 sed、awk 等 shell 命令的输出替换子字符串? 其他读者也可能会感兴趣。
感谢 @Gabriel 的原始 sed 内联代码。

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

I had to convert timestamps inline in my bash history to make sense to me.

Maybe the following coming from an answer to How do I replace a substring by the output of a shell command with sed, awk or such? could be interesting to other readers too.
Kudos for the original sed inline code go to @Gabriel.

cat ~/.bash_history | sed "s/^#\([0-9]\+\)$/echo -n '#'; date -u --d @\1 '\+\%Y-\%m-\%d \%T'/e" | less
流云如水 2024-08-31 05:18:27

如果您希望一次格式化多个时间戳,我编写了一个名为 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 构建它

If you're looking to format many timestamps all at once, I've written a C util called datefmt that formats timestamps in a text stream:

Let’s say we have some logs that contain unix timestamps:

$ cat logs.txt

EVENTS  1638499687   blahblah log1
EVENTS  1638499717   blahblah log2

We can pipe this log into datefmt to convert these timestamps into human-readable dates:

$ <logs.txt datefmt

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

Of course you can customize the format as well:

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

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

I've packaged this in NixOS, hopefully it will trickle out to other distros soon, but for now you will need to download the tarball and build it with make

微暖i 2024-08-31 05:18:27

在 PHP 中

$unix_time = 1256571985;

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

In PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文