Bagaimana cara mengubah cap waktu ke tanggal di Bash?

270

Saya memerlukan perintah shell atau skrip yang mengubah cap waktu Unix menjadi tanggal. Input dapat berasal dari parameter pertama atau dari stdin, memungkinkan untuk pola penggunaan berikut:

ts2date 1267619929

dan

echo 1267619929 | ts2date

Kedua perintah harus menampilkan "Rab 3 Mar 13:38:49 2010".

Chiborg
sumber

Jawaban:

532

Pada versi distribusi Linux yang umum, Anda dapat menggunakan:

date -d @1267619929
ya
sumber
5
One-liner:date -d @$(date -u +%s)
Mike Atlas
26
Untuk apa ini @? Saya tidak melihat itu di halaman manual GNU sama sekali.
Mark E. Haase
13
@mehaase - halaman manual mencatat bahwa string tanggal terlalu rumit untuk didokumentasikan di halaman manual, sehingga dijelaskan dalam info: info '(coreutils) invocation date'
MByD
10
brew install coreutils; gdate -d @1267619929
Mark Fox
2
info 'Date input formats' membuat Anda langsung ke datesimpul info pemformatan, dengan kutipan Robert Grudin yang bersangkutan, dan kemudian menu penentu format.
mike
165
date -r <number>

bekerja untuk saya di Mac OS X.

rafaelzlisboa
sumber
5
Ya, tapi itu tidak menangani sepersekian detik.
mgold
1
Dan itu membingungkan karena tidak bekerja seperti itu pada kebanyakan sistem linux, karena: freddy @ hades ~% date --help | grep - -r -r, --reference = FILE menampilkan waktu modifikasi terakhir FILE
frank42
1
sementara komentar pada jawaban ini benar, ini bukan kesalahan rafa, dan mereka tidak mengurangi jawabannya.
mike
29

Versi ini mirip dengan jawaban chiborg , tetapi menghilangkan kebutuhan untuk eksternal ttydan cat. Itu menggunakan date, tetapi bisa dengan mudah digunakan gawk. Anda dapat mengubah shebang dan mengganti tanda kurung ganda dengan yang tunggal dan ini juga akan berjalan 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
Dijeda sampai pemberitahuan lebih lanjut.
sumber
+1: jawaban yang sangat lengkap dan saya pikir tanggal lebih cepat dari gawk.
Bruno Brant
@ Bruno, bagaimana Anda tahu kencan lebih cepat dari gawk.?
ghostdog74
3
@ Bruno, @ ghostdog74: Di sistem saya, gawk(kira-kira) 15% lebih cepat dari datepada forloop berjangka waktu yang hanya terdiri dari gawk 'BEGIN { print strftime("%c", 1256571985); }'atau date -d '@1256571985' +%cdengan output diarahkan ke /dev/null.
Dijeda sampai pemberitahuan lebih lanjut.
1
tanggal sedikit (5%) lebih cepat daripada gawk untuk saya (mac osx 10.9.2, tanggal 8.23, gawk 4.1.1), tetapi keuntungan nyata (g) awk adalah menerima pipa kolom banyak cap waktu (lihat jawaban saya di bawah), yang membuat skrip misalnya 250x lebih cepat untuk 1000 cap waktu.
webb
3
Perhatikan bahwa jawaban saya memenuhi persyaratan OP seperti yang dinyatakan dalam pertanyaan, tetapi jawaban yang sekarang diterima tidak.
Dijeda sampai pemberitahuan lebih lanjut.
17

Anda dapat menggunakan tanggal GNU, misalnya,

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

atau

$ date -ud @1267619929
ghostdog74
sumber
10

Anda dapat menggunakan skrip awk sederhana ini:

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

Penggunaan sampel:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
codaddict
sumber
Ini tidak sesuai dengan penggunaan pertama - kadang-kadang saya tidak ingin mengulang TS dan menggunakan parameter sebagai gantinya.
chiborg
Pada beberapa versi busybox lama, date -s @tidak berfungsi, dan awkmasih berfungsi ! Contoh tanpa stdin akan sangat membantu juga.
Victor Sergienko
8

Sejak Bash 4.2 Anda dapat menggunakan printf's %(datefmt)TFormat:

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

Itu bagus, karena itu adalah shell builtin. Format untuk datefmt adalah string yang diterima oleh strftime(3)(lihat man 3 strftime). Ini %cadalah:

%c Representasi tanggal dan waktu yang dipilih untuk lokal saat ini.


Sekarang jika Anda ingin skrip yang menerima argumen dan, jika tidak ada yang disediakan, bertuliskan stdin, Anda dapat melanjutkan sebagai:

#!/bin/bash

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

Saya menggunakan ini saat mengonversi file log atau memonitornya:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
pengguna3544224
sumber
persis apa yang saya cari, dapat disingkat menjadiawk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue
5

Di OSX, atau BSD, ada -rflag setara yang tampaknya mengambil cap waktu unix. Berikut adalah contoh yang menjalankan tanggal empat kali: sekali untuk kencan pertama, untuk menunjukkan apa itu; satu untuk konversi ke unix timestamp dengan %s, dan akhirnya, satu yang, dengan -r, mengubah apa yang %smenyediakan kembali ke 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

Setidaknya, sepertinya bekerja di mesin saya.

$ 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
Daniel Farrell
sumber
Jika Anda sudah memiliki nilai cap waktu dan Anda hanya perlu menemukan tanggal yang setara, di OS X Anda cukup mengetik ini di baris perintah: date -r 1509453417
Noel Whitemore
1
Itu benar. Jika Anda melihat jawaban saya, saya sebenarnya menunjukkan itu.
Daniel Farrell
5

Anda bisa mendapatkan tanggal yang diformat dari cap waktu seperti ini

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"
andranikasl
sumber
Sebaliknya: date -ud "@ 1585667718" + '% Y-% m-% d% H:% M:% S'
AndiAna
3

Saya telah menulis skrip yang melakukan ini sendiri:

#!/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); }'
Chiborg
sumber
1
Tag pertanyaan Anda termasuk "bash", tetapi shebang Anda mengatakan "sh".
Dijeda sampai pemberitahuan lebih lanjut.
3

Dalam jawaban ini saya menyalin jawaban Dennis Williamson dan memodifikasinya sedikit untuk memungkinkan peningkatan kecepatan yang besar ketika memipis kolom banyak cap waktu ke skrip. Misalnya, mem-pipkan 1000 cap waktu ke skrip asli dengan xargs -n1 di komputer saya menggunakan 6.929s dibandingkan dengan 0.027s dengan versi modifikasi ini:

#!/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
webb
sumber
2

beberapa contoh:

$ date
Selasa 22 Maret 16:47:06 CST 2016

$ date -d "Sel 22 Mar 16:47:06 CST 2016" "+% s"
1458636426

$ date +% s
1458636453

$ date -d @ 1458636426
Selasa 22 Maret 16:47:06 CST 2016

$ date --date = '@ 1458636426'
Selasa 22 Maret 16:47:06 CST 2016


kai
sumber
2

Saya menggunakan cross-platform one-liner ini:

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

Ini harus bekerja di kedua macOS dan versi yang lebih baru dari distribusi Linux umum.

Blago
sumber
0

Meskipun bukan bash murni, skrip berikut akan mengonversi stempel waktu dengan panjang 13 dalam string ke tanggal yang setara di zona waktu lokal Anda menggunakan 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"

memasukkan

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

keluaran

$ 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"}
Taman Brad
sumber
-8

Dalam PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
Lucas
sumber
5
Bagus, tapi saya hanya ingin menggunakan bash.
chiborg