Как конвертировать временные метки в даты в Bash?


мне нужна команда или скрипт, который преобразует метку времени Unix для даты. Входные данные могут поступать либо из первого параметра, либо из stdin, что позволяет использовать следующие шаблоны:

ts2date 1267619929

и

echo 1267619929 | ts2date

обе команды должны вывести "Wed Mar 3 13: 38: 49 2010".

12 191

12 ответов:

в более поздних версиях популярных дистрибутивов Linux вы можете использовать:

date -d @1267619929
date -r <number>

работает для меня на Mac OS X.

эта версия похожа на chiborg это ответ, но он устраняет необходимость во внешнем tty и cat. Он использует date, но может так же легко использовать gawk. Вы можете изменить shebang и заменить двойные квадратные скобки на одиночные, и это также будет работать в sh.

#!/bin/bash
LANG=C
if [[ -z "" ]]
then
    if [[ -p /dev/stdin ]]    # input from a pipe
    then
        read -r p
    else
        echo "No timestamp given." >&2
        exit
    fi
else
    p=
fi
date -d "@$p" +%c

вы можете использовать GNU date, например,

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

или

$ date -ud @1267619929

Вы можете использовать этот простой скрипт на awk:

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

пример использования:

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$

Я использую это при преобразовании файлов журнала или их мониторинге:

tail -f <log file> | gawk \
'{ printf strftime("%c", ); for (i=2; i<NF; i++) printf $i " "; print $NF }'

Я написал скрипт, который делает это сам:

#!/bin/bash
LANG=C
if [ -z "" ]; then
    if [  "$(tty)" = "not a tty" ]; then
            p=`cat`;
    else
            echo "No timestamp given."
            exit
    fi
else
    p=
fi
echo $p | gawk '{ print strftime("%c", ); }'

в этом ответе я копирую ответ Денниса Уильямсона и немного изменяю его, чтобы обеспечить значительное увеличение скорости при передаче столбца с несколькими метками времени в сценарий. Например, передача 1000 меток времени в исходный скрипт с xargs-n1 на моей машине заняла 6.929 С, а не 0.027 с этой модифицированной версией:

#!/bin/bash
LANG=C
if [[ -z "" ]]
then
    if [[ -p /dev/stdin ]]    # input from a pipe
    then
        cat - | gawk '{ print strftime("%c", ); }'
    else
        echo "No timestamp given." >&2
        exit
    fi
else
    date -d @ +%c
fi

в OSX, или BSD, есть эквивалент -r флаг, который, по-видимому, принимает метку времени unix. Вот пример, который запускает дату четыре раза: один раз для первой даты, чтобы показать, что это такое; один для преобразования в unix timestamp с %s, и, наконец, тот, который, с -r, преобразует то, что %s возвращает к строке.

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

по крайней мере, кажется, работает на моей машине.

$ 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

так как Bash 4.2 вы можете использовать printf ' s :

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

это хорошо, потому что это встроено в оболочку. Формат для datefmt - это строка принята strftime(3) (см. man 3 strftime). Здесь %c - это:

%c предпочтительное представление даты и времени для текущего место действия.


теперь, если вы хотите скрипт, который принимает аргумент и, если он не указан, читает stdin, вы можете действовать следующим образом:

#!/bin/bash

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

пример:

$ 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


в PHP

$unix_time = 1256571985;

echo date("Y-m-d H:i:s",$unix_time)