Comment convertir des horodatages en dates dans Bash?

270

J'ai besoin d'une commande shell ou d'un script qui convertit un horodatage Unix en une date. L'entrée peut provenir du premier paramètre ou de stdin, permettant les modèles d'utilisation suivants:

ts2date 1267619929

et

echo 1267619929 | ts2date

Les deux commandes doivent afficher "Wed Mar 3 13:38:49 2010".

chiborg
la source

Réponses:

532

Sur les versions ultérieures des distributions Linux courantes, vous pouvez utiliser:

date -d @1267619929
a'r
la source
5
Vol simple:date -d @$(date -u +%s)
Mike Atlas du
26
À quoi ça sert @? Je ne vois pas du tout cela dans la page de manuel GNU.
Mark E. Haase
13
@mehaase - la page de manuel note que la chaîne de date est trop complexe pour être documentée dans la page de manuel, elle est donc décrite dans info: info '(coreutils) date invocation'
MByD
10
brew install coreutils; gdate -d @1267619929
Mark Fox
2
info 'Date input formats' vous amène directement au datenœud d'informations de mise en forme, avec la citation pertinente de Robert Grudin, puis un menu de spécificateurs de format.
mike
165
date -r <number>

fonctionne pour moi sur Mac OS X.

rafaelzlisboa
la source
5
Oui, mais il ne gère pas des fractions de seconde.
mgold
1
Et c'est déroutant car cela ne fonctionne pas de cette façon sur la plupart des systèmes Linux, car: freddy @ hades ~% date --help | grep - -r -r, --reference = FILE affiche l'heure de la dernière modification de FILE
frank42
1
Bien que les commentaires sur cette réponse soient vrais, ce n'est pas la faute de Rafa, et ils ne diminuent pas sa réponse.
mike
29

Cette version est similaire à la réponse de chiborg , mais elle élimine le besoin des externes ttyet des cat. Il utilise date, mais pourrait tout aussi facilement utiliser gawk. Vous pouvez changer le shebang et remplacer les crochets doubles par des crochets simples et cela fonctionnera également 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
En pause jusqu'à nouvel ordre.
la source
+1: réponse très complète et je pense que la date est plus rapide que gawk.
Bruno Brant
@Bruno, comment savez-vous que la date est plus rapide que gawk.?
ghostdog74
3
@Bruno, @ ghostdog74: Sur mon système, gawkest (très grossièrement) 15% plus rapide que datedans une forboucle temporisée composée uniquement de gawk 'BEGIN { print strftime("%c", 1256571985); }'ou date -d '@1256571985' +%cavec une sortie redirigée vers /dev/null.
pause jusqu'à nouvel ordre.
1
la date est légèrement (5%) plus rapide que gawk pour moi (mac osx 10.9.2, date 8.23, gawk 4.1.1), mais le véritable avantage de (g) awk est d'accepter un tube d'une colonne de plusieurs horodatages (voir ma réponse ci-dessous), ce qui rend le script par exemple 250x plus rapide pour 1000 horodatages.
webb du
3
Notez que ma réponse répond aux exigences du PO comme indiqué dans la question, mais la réponse maintenant acceptée ne le fait pas.
pause jusqu'à nouvel ordre.
17

Vous pouvez utiliser la date GNU, par exemple,

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

ou

$ date -ud @1267619929
ghostdog74
la source
10

Vous pouvez utiliser ce simple script awk:

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

Exemple d'utilisation:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
codaddict
la source
Cela ne correspond pas à la première utilisation - parfois je ne veux pas faire écho au TS et utiliser un paramètre à la place.
chiborg
Sur une ancienne version de busybox, date -s @ne fonctionne pas, et fonctionne awktoujours! Un exemple sans stdin serait également utile.
Victor Sergienko
8

Depuis Bash 4.2, vous pouvez utiliser printfle %(datefmt)Tformat de:

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

C'est bien, car c'est un shell intégré. Le format de datefmt est une chaîne acceptée par strftime(3)(voir man 3 strftime). Voici %c:

%c Représentation préférée de la date et de l'heure pour les paramètres régionaux actuels.


Maintenant, si vous voulez un script qui accepte un argument et, si aucun n'est fourni, lit stdin, vous pouvez procéder comme suit:

#!/bin/bash

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

J'utilise ceci lors de la conversion de fichiers journaux ou de leur surveillance:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
user3544224
la source
exactement ce que je cherchais, peut être raccourci enawk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue
5

Dans OSX ou BSD, il y a un -rdrapeau équivalent qui prend apparemment un horodatage Unix. Voici un exemple qui exécute la date quatre fois: une fois pour la première date, pour montrer de quoi il s'agit; un pour la conversion en horodatage unix avec %s, et enfin, un qui, avec -r, convertit ce qui %srenvoie en chaîne.

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

Au moins, semble fonctionner sur ma 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
Daniel Farrell
la source
Si vous avez déjà une valeur d'horodatage et que vous avez juste besoin de trouver la date équivalente, dans OS X, vous pouvez simplement la saisir sur la ligne de commande: date -r 1509453417
Noel Whitemore
1
C'est vrai. Si vous regardez ma réponse, je le démontre.
Daniel Farrell
5

Vous pouvez obtenir une date formatée à partir d'un horodatage comme celui-ci

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

J'ai écrit un script qui le fait moi-même:

#!/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
la source
1
Vos balises de question incluent «bash», mais votre shebang dit «sh».
pause jusqu'à nouvel ordre.
3

Dans cette réponse, je copie la réponse de Dennis Williamson et la modifie légèrement pour permettre une augmentation considérable de la vitesse lors du transfert d'une colonne de nombreux horodatages vers le script. Par exemple, le raccordement de 1000 horodatages au script d'origine avec xargs -n1 sur ma machine a pris 6,929s contre 0,027s avec cette version modifiée:

#!/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
la source
2

un exemple:

$ date
Mar 22 22 16:47:06 CST 2016

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

$ date +% s
1458636453

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

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


kai
la source
2

J'utilise ce one-liner multi-plateforme:

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

Il devrait fonctionner à la fois dans macOS et dans les versions ultérieures des distributions Linux courantes.

Blago
la source
0

Bien qu'il ne soit pas purement bash, le script suivant convertira les horodatages de longueur 13 dans une chaîne en leur date équivalente dans votre fuseau horaire local en utilisant 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"

contribution

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

production

$ 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
la source
-8

En PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
Lucas
la source
5
Bien, mais je voulais juste utiliser bash.
chiborg