Как конвертировать метки времени в даты в Bash? - PullRequest
231 голосов
/ 03 марта 2010

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

ts2date 1267619929

и

echo 1267619929 | ts2date

Обе команды должны вывести «Ср 3 марта 13:38:49 2010».

Ответы [ 13 ]

466 голосов
/ 03 марта 2010

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

date -d @1267619929
146 голосов
/ 26 октября 2012
date -r <number>

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

27 голосов
/ 03 марта 2010

Эта версия похожа на ответ Чиборга , но устраняет необходимость во внешних tty и cat. Он использует date, но может так же легко использовать gawk. Вы можете изменить шебанг и заменить квадратные скобки одинарными, и это также будет работать в 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
17 голосов
/ 03 марта 2010

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

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

или

$ date -ud @1267619929
10 голосов
/ 03 марта 2010

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

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

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

$ echo '1098181096' | ./a.awk 
Tue 19 Oct 2004 03:18:16 AM PDT
$
6 голосов
/ 13 сентября 2017

Начиная с Bash 4.2, вы можете использовать printf %(datefmt)T формат:

$ 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
6 голосов
/ 17 апреля 2014

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

tail -f <log file> | gawk \
'{ printf strftime("%c", $1); for (i=2; i<NF; i++) printf $i " "; print $NF }'
3 голосов
/ 25 октября 2017

В 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
3 голосов
/ 26 сентября 2014

В этом ответе я копирую ответ Денниса Уильямсона и слегка его изменяю, чтобы значительно увеличить скорость при передаче столбца с множеством временных меток в сценарий. Например, передача 1000 временных меток к исходному сценарию с xargs -n1 на моем компьютере заняла 6,929 с, а не 0,027 с этой модифицированной версией:

#!/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 голосов
/ 03 марта 2010

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

#!/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); }'
...