Câu trả lời:
Trên các phiên bản sau của các bản phân phối Linux phổ biến, bạn có thể sử dụng:
date -d @1267619929
@
? Tôi không thấy điều đó trong trang GNU GNU.
brew install coreutils; gdate -d @1267619929
info 'Date input formats'
giúp bạn đi thẳng đến date
nút thông tin định dạng, với trích dẫn thích hợp của Robert Grudin, và sau đó là một menu các công cụ định dạng.
date -r <number>
hoạt động với tôi trên Mac OS X.
Phiên bản này tương tự như câu trả lời của chiborg , nhưng nó loại bỏ sự cần thiết của bên ngoài tty
và cat
. Nó sử dụng date
, nhưng có thể dễ dàng sử dụng gawk
. Bạn có thể thay đổi shebang và thay thế dấu ngoặc vuông bằng một dấu ngoặc đơn và điều này cũng sẽ chạy trong 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
gawk
nhanh hơn 15% so với vòng lặp date
thời gian for
chỉ bao gồm gawk 'BEGIN { print strftime("%c", 1256571985); }'
hoặc date -d '@1256571985' +%c
có đầu ra được chuyển hướng đến /dev/null
.
Bạn có thể sử dụng ngày GNU, ví dụ,
$ sec=1267619929
$ date -d "UTC 1970-01-01 $sec secs"
hoặc là
$ date -ud @1267619929
Bạn có thể sử dụng tập lệnh awk đơn giản này:
#!/bin/gawk -f
{ print strftime("%c", $0); }
Sử dụng mẫu:
$ echo '1098181096' | ./a.awk
Tue 19 Oct 2004 03:18:16 AM PDT
$
date -s @
không hoạt động, và awk
vẫn còn! Một ví dụ không có stdin cũng sẽ hữu ích.
Kể từ Bash 4.2 bạn có thể sử dụng printf
là %(datefmt)T
định dạng:
$ printf '%(%c)T\n' 1267619929
Wed 03 Mar 2010 01:38:49 PM CET
Điều đó thật tuyệt, bởi vì nó là một vỏ dựng sẵn. Định dạng cho datefmt là một chuỗi được chấp nhận bởi strftime(3)
(xem man 3 strftime
). Đây %c
là:
%c
Đại diện ngày và thời gian ưa thích cho miền địa phương hiện tại.
Bây giờ nếu bạn muốn một tập lệnh chấp nhận một đối số và, nếu không được cung cấp, đọc stdin, bạn có thể tiến hành như sau:
#!/bin/bash
if (($#)); then
printf '%(%c)T\n' "$@"
else
while read -r line; do
printf '%(%c)T\n' "$line"
done
fi
Tôi sử dụng điều này khi chuyển đổi tệp nhật ký hoặc theo dõi chúng:
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; }'
Trong OSX hoặc BSD, có một -r
cờ tương đương có dấu thời gian unix. Đây là một ví dụ chạy ngày bốn lần: một lần cho ngày đầu tiên, để hiển thị nó là gì; một cho việc chuyển đổi thành dấu thời gian unix với %s
, và cuối cùng, một trong đó, với -r
, chuyển đổi những gì %s
cung cấp trở lại thành một chuỗi.
$ date; date +%s; date -r `date +%s`
Tue Oct 24 16:27:42 CDT 2017
1508880462
Tue Oct 24 16:27:42 CDT 2017
Ít nhất, dường như làm việc trên máy của tôi.
$ 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
Bạn có thể nhận được định dạng ngày từ dấu thời gian như thế này
date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"
Tôi đã viết một kịch bản tự làm điều này:
#!/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); }'
Trong câu trả lời này, tôi sao chép câu trả lời của Dennis Williamson và sửa đổi nó một chút để cho phép tăng tốc độ rất lớn khi đưa một cột có nhiều dấu thời gian vào kịch bản. Ví dụ: chuyển 1000 dấu thời gian sang tập lệnh gốc với xargs -n1 trên máy của tôi mất 6,929 so với 0,027 giây với phiên bản sửa đổi này:
#!/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
một số ví dụ:
$ ngày Thứ ba ngày 22 tháng 3 16:47:06 CST 2016 $ ngày -d "Thứ ba ngày 22 tháng 3 16:47:06 CST 2016" "+% s" 1458636426 $ ngày +% s 1458636453 $ ngày -d @ 1458636426 Thứ ba ngày 22 tháng 3 16:47:06 CST 2016 $ ngày - ngày = '@ 1458636426' Thứ ba ngày 22 tháng 3 16:47:06 CST 2016
Mặc dù không phải là bash thuần túy, tập lệnh sau sẽ chuyển đổi dấu thời gian có độ dài 13 trong chuỗi thành ngày tương đương của chúng trong múi giờ địa phương của bạn bằng cách sử dụng perl
#!/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 @$(date -u +%s)