Cómo convertir marcas de tiempo a fechas en Bash?


Necesito un comando o script de shell que convierta una marca de tiempo Unix en una fecha. La entrada puede venir desde el primer parámetro o desde stdin, permitiendo los siguientes patrones de uso:

ts2date 1267619929

Y

echo 1267619929 | ts2date

Ambos comandos deben salir "Mié Mar 3 13:38:49 2010".

Author: Peter Mortensen, 2010-03-03

12 answers

En versiones posteriores de distribuciones comunes de Linux puede usar:

date -d @1267619929
 403
Author: a'r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-03 12:47:51
date -r <number>

Funciona para mí en Mac OS X.

 129
Author: rafaelzlisboa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-22 12:52:23

Esta versión es similar a respuesta de chiborg, pero elimina la necesidad de la externa tty y cat. Usa date, pero podría usar gawk con la misma facilidad. Puede cambiar el shebang y reemplazar los corchetes dobles por corchetes simples y esto también se ejecutará en 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
 24
Author: Dennis Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 17:13:39

Puede usar GNU date, por ejemplo,

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

O

$ date -ud @1267619929
 13
Author: ghostdog74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-11 09:40:12

Puedes usar este sencillo script awk:

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

Uso de la muestra:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
 9
Author: codaddict,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-03 12:45:09

Uso esto al convertir archivos de registro o monitorearlos:

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
 4
Author: user3544224,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-17 07:58:03

He escrito un guion que hace esto yo mismo:

#!/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); }'
 3
Author: chiborg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-03 13:41:54

En esta respuesta copio la respuesta de Dennis Williamson y la modifico ligeramente para permitir un gran aumento de velocidad al canalizar una columna de muchas marcas de tiempo al script. Por ejemplo, la canalización de 1000 marcas de tiempo al script original con xargs-n1 en mi máquina tomó 6.929 s en lugar de 0.027 s con esta versión modificada:

#!/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
 3
Author: webb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-25 23:08:14

En OSX, o BSD, hay una bandera -r equivalente que aparentemente toma una marca de tiempo unix. Aquí hay un ejemplo que ejecuta date cuatro veces: una para la primera fecha, para mostrar lo que es; una para la conversión a marca de tiempo unix con %s, y finalmente, una que, con -r, convierte lo que %s proporciona de nuevo a una cadena.

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

Al menos, parece funcionar en mi máquina.

$ 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
 2
Author: Dan Farrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-24 21:46:46

Desde Bash 4.2 puedes usar el formato printf's %(datefmt)T:

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

Eso es bueno, porque es una concha incorporada. El formato para datefmt es una cadena aceptada por strftime(3) (véase man 3 strftime). Aquí %c es:

%c La representación de fecha y hora preferida para el actual local.


Ahora, si desea un script que acepte un argumento y, si no se proporciona ninguno, lea stdin, puede proceder como:

#!/bin/bash

if (($#)); then
    printf '%(%c)T\n' "$@"
else
    while read -r line; do
        printf '%(%c)T\n' "$line"
    done
fi
 1
Author: gniourf_gniourf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 17:27:57

Algún ejemplo:

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

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

$ date +%s
1458636453

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

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


 0
Author: kai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-22 08:58:33

En PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)
 -7
Author: Lucas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-03 12:43:35