Wie konvertiere ich Zeitstempel in Datumsangaben in Bash?

270

Ich benötige einen Shell-Befehl oder ein Shell-Skript, das einen Unix-Zeitstempel in ein Datum konvertiert. Die Eingabe kann entweder vom ersten Parameter oder von stdin stammen, wobei die folgenden Verwendungsmuster berücksichtigt werden:

ts2date 1267619929

und

echo 1267619929 | ts2date

Beide Befehle sollten "Wed Mar 3 13:38:49 2010" ausgeben.

Chiborg
quelle

Antworten:

531

In späteren Versionen gängiger Linux-Distributionen können Sie Folgendes verwenden:

date -d @1267619929
a'r
quelle
5
Einzeiler:date -d @$(date -u +%s)
Mike Atlas
26
Wofür ist das @? Ich sehe das überhaupt nicht in der GNU-Manpage.
Mark E. Haase
13
@mehaase - Die Manpage stellt fest, dass die Datumszeichenfolge zu komplex ist, um in der Manpage dokumentiert zu werden. Daher wird sie in info: info '(coreutils) date invocation'
MByD
10
brew install coreutils; gdate -d @1267619929
Mark Fox
2
info 'Date input formats' Sie gelangen direkt zum dateFormatierungsinfoknoten mit dem entsprechenden Robert Grudin-Zitat und einem Menü mit Formatspezifizierern.
Mike
165
date -r <number>

funktioniert für mich unter Mac OS X.

rafaelzlisboa
quelle
5
Ja, aber es werden keine Sekundenbruchteile verarbeitet.
mgold
1
Und es ist verwirrend, weil es auf den meisten Linux-Systemen nicht so funktioniert, weil: freddy @ hades ~% date --help | grep - -r -r, --reference = FILE zeigt die letzte Änderungszeit von FILE an
frank42
1
Während die Kommentare zu dieser Antwort wahr sind, sind diese nicht Rafas Schuld und sie mindern seine Antwort nicht.
Mike
29

Diese Version ähnelt der Antwort von Chiborg , macht jedoch externe ttyund überflüssigcat . Es verwendet date, könnte aber genauso einfach verwenden gawk. Sie können den Shebang ändern und die doppelten eckigen Klammern durch einzelne ersetzen. Dies wird auch ausgeführt 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
Bis auf weiteres angehalten.
quelle
+1: sehr vollständige Antwort und ich denke, das Datum ist schneller als gawk.
Bruno Brant
@ Bruno, woher weißt du, dass das Datum schneller ist als Gawk?
Ghostdog74
3
@Bruno, @ ghostdog74: Auf meinem System gawkist es (ungefähr) 15% schneller als datein einer Zeitschleife for, die nur aus gawk 'BEGIN { print strftime("%c", 1256571985); }'oder date -d '@1256571985' +%cmit umgeleiteter Ausgabe besteht /dev/null.
Bis auf weiteres angehalten.
1
Datum ist für mich geringfügig (5%) schneller als Gawk (Mac OSX 10.9.2, Datum 8.23, Gawk 4.1.1), aber der wahre Vorteil von (g) Awk besteht darin, eine Pipe einer Spalte mit vielen Zeitstempeln zu akzeptieren (siehe meine Antwort unten), wodurch das Skript zB 250x so schnell für 1000 Zeitstempel ist.
Webb
3
Beachten Sie, dass meine Antwort den in der Frage angegebenen Anforderungen des OP entspricht, die jetzt akzeptierte Antwort jedoch nicht.
Bis auf weiteres angehalten.
17

Sie können beispielsweise das GNU-Datum verwenden

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

oder

$ date -ud @1267619929
Ghostdog74
quelle
10

Sie können dieses einfache awk-Skript verwenden:

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

Beispielnutzung:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
Codaddict
quelle
Dies passt nicht zur ersten Verwendung - manchmal möchte ich den TS nicht wiederholen und stattdessen einen Parameter verwenden.
Chiborg
Funktioniert bei einigen alten Busybox-Versionen date -s @nicht und awkfunktioniert immer noch! Ein Beispiel ohne Standard wäre auch hilfreich.
Victor Sergienko
8

Seit 4.2 Bash können Sie mit printf‚s - %(datefmt)TFormat:

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

Das ist schön, weil es eine eingebaute Shell ist. Das Format für datefmt ist eine Zeichenfolge, die von strftime(3)(siehe man 3 strftime) akzeptiert wird . Hier %cist:

%c Die bevorzugte Datums- und Uhrzeitdarstellung für das aktuelle Gebietsschema.


Wenn Sie nun ein Skript möchten, das ein Argument akzeptiert und, falls keines angegeben ist, stdin liest, können Sie wie folgt vorgehen:

#!/bin/bash

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

Ich verwende dies beim Konvertieren oder Überwachen von Protokolldateien:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
user3544224
quelle
genau das, wonach ich gesucht habe, kann aufawk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue
5

In OSX oder BSD gibt es ein gleichwertiges -rFlag, das anscheinend einen Unix-Zeitstempel benötigt. Hier ist ein Beispiel, das Datum viermal ausführt: einmal für das erste Datum, um zu zeigen, was es ist; eine für die Konvertierung in einen Unix-Zeitstempel mit %sund schließlich eine, die mit -rkonvertiert, was %szurück in einen String liefert.

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

Zumindest scheint auf meiner Maschine zu funktionieren.

$ 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
quelle
Wenn Sie bereits einen Zeitstempelwert haben und nur das entsprechende Datum suchen müssen, können Sie dies in OS X einfach über die Befehlszeile eingeben: Datum -r 1509453417
Noel Whitemore
1
Das ist richtig. Wenn Sie sich meine Antwort ansehen, zeige ich das tatsächlich.
Daniel Farrell
5

Sie können das formatierte Datum aus einem solchen Zeitstempel abrufen

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

Ich habe ein Skript geschrieben, das dies selbst macht:

#!/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
quelle
1
Ihre Frage-Tags enthalten "Bash", aber Ihr Shebang sagt "sh".
Bis auf weiteres angehalten.
3

In dieser Antwort kopiere ich die Antwort von Dennis Williamson und ändere sie leicht, um eine enorme Geschwindigkeitssteigerung zu ermöglichen, wenn eine Spalte mit vielen Zeitstempeln an das Skript weitergeleitet wird. Das Weiterleiten von 1000 Zeitstempeln an das ursprüngliche Skript mit xargs -n1 auf meinem Computer dauerte beispielsweise 6,929 Sekunden im Gegensatz zu 0,027 Sekunden bei dieser modifizierten 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
webb
quelle
2

ein Beispiel:

$ Datum
Di 22. März 16:47:06 CST 2016

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

$ date +% s
1458636453

$ date -d @ 1458636426
Di 22. März 16:47:06 CST 2016

$ date --date = '@ 1458636426'
Di 22. März 16:47:06 CST 2016


kai
quelle
2

Ich benutze diesen plattformübergreifenden Einzeiler:

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

Es sollte sowohl in macOS als auch in späteren Versionen gängiger Linux-Distributionen funktionieren.

Blago
quelle
0

Das folgende Skript ist zwar kein reines Bash, konvertiert jedoch Zeitstempel der Länge 13 in einer Zeichenfolge mithilfe von Perl in das entsprechende Datum in Ihrer lokalen Zeitzone

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"

Eingang

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

Ausgabe

$ 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"}
Brad Parks
quelle
-8

In PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
Lucas
quelle
5
Schön, aber ich wollte nur Bash verwenden.
Chiborg