是否有一种快速的、一行程序的方法将 Unix 时间戳从 Unix 命令行转换为日期?
date也许可以工作,但是指定每个元素(月、日、年、小时等)相当麻烦,而且我不知道如何让它正常工作。似乎有一个更简单的方法ーー我是不是漏掉了什么?
date
awk 'BEGIN { print strftime("%c", 1271603087); }'
使用 GNU 核心组件中的 date,你可以做到:
date -d "@$TIMESTAMP"
# date -d @0 Wed Dec 31 19:00:00 EST 1969
(来自: 将 Unix 时间戳转换为日期)
在 OS X 上,使用 date -r。
date -r
date -r "$TIMESTAMP"
或者,使用 strftime()。它不能直接从 shell 中获得,但是您可以通过 发呆访问它。%c说明符以依赖于区域设置的方式显示时间戳。
strftime()
%c
echo "$TIMESTAMP" | gawk '{print strftime("%c", $0)}'
# echo 0 | gawk '{print strftime("%c", $0)}' Wed 31 Dec 1969 07:00:00 PM EST
date -d @1278999698 +'%Y-%m-%d %H:%M:%S' 在 @后面的数字是以秒为单位的数字
date -d @1278999698 +'%Y-%m-%d %H:%M:%S'
@
如果你觉得这个符号不好用,也许 -R选项确实有帮助。它以 RFC2822格式输出日期。所以您不需要所有这些标识符: date -d @1278999698 -R。另一种可能性是在区域设置中以秒为单位输出日期: date -d @1278999698 +%c。应该很好记。:-)
-R
date -d @1278999698 -R
date -d @1278999698 +%c
标准的 Perl 解决方案是:
echo $TIMESTAMP | perl -nE 'say scalar gmtime $_'
(或本地时间,如果喜欢)
此解决方案使用不支持 date -d @的日期版本。它不需要 AWK或其他命令。Unix 时间戳是自1970年1月1日以来的秒数,因此指定 UTC 很重要。
date -d @
date -d '1970-01-01 1357004952 sec UTC' Mon Dec 31 17:49:12 PST 2012
如果你使用的是 Mac,那么使用:
date -r 1357004952
获得新纪元的命令:
date +%s 1357004952
归功于安东: BASH: 将 Unix 时间戳转换为日期
正如@TomMcKenzie 在对另一个答案的评论中所说,date -r 123456789可以说是 Unix 时代以来更为普遍(即实现更广泛)的简单解决方案,但不幸的是,没有通用的保证便携式解决方案。
date -r 123456789
在许多类型的系统上,-d选项的含义与 GNUDate 的 --date扩展完全不同。遗憾的是,GNUDate 对 -r的解释与这些其他实现不同。所以不幸的是,您必须知道您使用的是哪个版本的 date,而且许多较老的 Unixdate命令不支持这两种选项。
-d
--date
-r
更糟糕的是,POSIX date既不能识别 -d也不能识别 -r,而且根本没有在任何命令中(据我所知)提供从命令行格式化 Unix 时间的标准方法(因为 POSIX Awk 也缺少 strftime())。(不能使用 touch -t和 ls,因为前者不接受 Unix 时代以来的秒数。)
touch -t
ls
注意,尽管 Brian Kernighan 直接提供的 One True Awk 现在内置了 strftime()函数和 systime()函数来返回 Unix 时代以来的当前时间(以秒为单位) ,所以也许 Awk 解决方案是最便携的。
systime()
对上面的答案稍作修正。请将时区指定为 UTC,而不是 GMT:
$ date -d '1970-01-01 1416275583 sec GMT' Tue Nov 18 00:53:03 GMT 2014 $ date -d '1970-01-01 1416275583 sec UTC' Tue Nov 18 01:53:03 GMT 2014
第二个是正确的。我认为这是因为在英国,夏令时从1968年到1971年一直在实施。
这里的其他例子很难记住,最简单的例子是:
date -r 1305712800
在你的 ~/. bashrc 中加入以下内容:
function unixts() { date -d "@$1"; }
示例用法:
$ unixts 1551276383 Wed Feb 27 14:06:23 GMT 2019
巨蟒:
python -c "from datetime import datetime; print(datetime.fromtimestamp($TIMESTAMP))"
由于这个问题被标记为 Bash,这里没有答案地址为 printf 抨击:
printf
printf '%(fmt)T' $UNIXEPOCH
在 bash 下,来自 V4.2(2011年2月) ,printf 内置有一个 %(fmt)T说明符,它允许时间值使用类似 strftime 的格式。
%(fmt)T
TZ=UTC LANG=C printf '%(%A %d %b %Y, %T %Z)T\n' 12345678 Saturday 23 May 1970, 21:21:18 UTC
使用时不带参数或与 -1作为参数,这将打印当前时间:
-1
printf '%(%b %d, %T)T\n' Aug 03, 08:42:28
当 printf为命令行中出现的所有参数重复 格式顺序时:
$ TZ=UTC LANG=C printf '%(%A %d %b %Y, %T %Z)T\n' -1 123456789 $EPOCHSECONDS Sunday 20 Nov 2022, 13:04:42 UTC Thursday 29 Nov 1973, 21:33:09 UTC Sunday 20 Nov 2022, 13:04:42 UTC
没有参数,没有 fmt字符串,printf '%()T'将打印当前时间:
fmt
printf '%()T'
printf '%()T\n' 12:34:56 echo $(( $(TZ=UTC printf "%()T" | sed 's/:/* 3600 +/;s/:/* 60 +/') - $(printf "%(%s)T") % 86400 )) 0
$EPOCHSECONDS
$EPOCHREALTIME
从 V5.0开始,bash 的环境提供了两个整数变量: 以秒为单位展开的 $EPOCHSECONDS和以微秒为单位展开的以秒为单位的 $EPOCHREALTIME。.
myvar1=$(LANG=C date -d 'now -1 day' +%c) LANG=C printf -v myvar2 '%(%c)T' $(( EPOCHSECONDS - 86400 )) [[ $myvar1 == "$myvar2" ]] || echo "Something's wrong: '$myvar1' != '$myvar2'!"
除了在一个非常小的时间圈,其中时间四舍五入到第二次增量之间设置 $myvar1和 $myvar2一秒,这段代码不会产生任何输出,因为 $myvar1应该包含完全相同的字符串比 $myvar2。
$myvar1
$myvar2
declare -p myvar{1,2} declare -- myvar1="Tue Aug 2 11:11:35 2022" declare -- myvar2="Tue Aug 2 11:11:35 2022"
由于 printf是 天生的,因此没有 叉子用于从 UNIXTIME 转换中分配字符串变量。
唯一的区别是资源占用量,然后是执行时间。
关于 $EPOCHREALTIME的进一步信息和建议,请参阅 如何使用 bash 内置打印以微秒为单位的当前时间
-f
使用 GNU date,如果计划格式化大量的 Unixtime戳,可以使用 date命令作为过滤器。
首先,必须在每个时间戳之前添加一个 强 > At强(@) ,然后 date -f可以在一个操作中处理每个输入行:
At
date -f
sed 's/^/@/' < inputfile | date -f - +'%A %d %b %Y, %T %Z'
样本:
seq 123456789 $(((EPOCHSECONDS-123456789)/4)) $EPOCHSECONDS | sed 's/^/@/' | LANG=C TZ=GMT date -f - +'%A %d %b %Y, %T %Z'
应该产生这样的东西:
Thursday 29 Nov 1973, 21:33:09 GMT Thursday 30 Jan 1986, 11:53:49 GMT Thursday 02 Apr 1998, 02:14:29 GMT Wednesday 02 Jun 2010, 16:35:09 GMT Wednesday 03 Aug 2022, 06:55:49 GMT
使用 tail -f squid/access.log的示例,来自远程服务器。
tail -f squid/access.log
squid日志看起来像:
squid
1659526597.212 240128 192.168.0.184 TCP_TUNNEL/200 3383 CONNECT safebrowsing.googleapis.com:443 - HIER_DIRECT/172.217.168.74 - 1659526614.078 753 192.168.0.91 TCP_TUNNEL/200 3800 CONNECT shavar.services.mozilla.com:443 - HIER_DIRECT/44.236.110.253 -
为了能够远程跟踪一些 乌贼代理,我可以使用这个:
exec {fd}<> <(:) # This will open unnamed fifo.
然后
ssh root@proxyserver tail -f /var/log/squid/access.log | tee >( exec sed -ue 's/^\([0-9]\+\)\..*/@\1/'| stdbuf -i0 -o0 date -f - +%c >/dev/fd/$fd ) | sed -ue 's/^[0-9]\+\././'| paste -d '' /dev/fd/$fd -
这将输出没有缓冲,如下所示:
Wed Aug 3 13:36:37 2022.212 240128 192.168.0.184 TCP_TUNNEL/200 3383 CONNECT safebrowsing.googleapis.com:443 - HIER_DIRECT/172.217.168.74 - Wed Aug 3 13:36:54 2022.078 753 192.168.0.91 TCP_TUNNEL/200 3800 CONNECT shavar.services.mozilla.com:443 - HIER_DIRECT/44.236.110.253 -
可以通过 Ctrl + C停止,然后重新运行多次,直到通过以下方法关闭 $fd:
$fd
exec {fd}<&-