Як конвертувати часові позначки на дати в Bash?


270

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

ts2date 1267619929

і

echo 1267619929 | ts2date

Обидві команди повинні вивести "ср. 3 березня 13:38:49 2010".

Відповіді:


531

На пізніших версіях поширених дистрибутивів Linux можна використовувати:

date -d @1267619929

5
Однолінійний:date -d @$(date -u +%s)
Майк Атлас

26
Для чого це @? Я взагалі цього не бачу на сторінці людини GNU.
Марк Е. Хааз

13
@mehaase - сторінка man зазначає, що рядок дати занадто складний, щоб бути задокументованим на сторінці сторінки, тому він описаний в info: info '(coreutils) виклик дати' '
MByD

10
brew install coreutils; gdate -d @1267619929
Марк Фокс

2
info 'Date input formats' переводить вас до dateінформаційного вузла форматування з відповідним цитатом Роберта Грудіна, а потім меню специфікаторів формату.
Майк

165
date -r <number>

працює для мене на Mac OS X.


5
Так, але це не обробляє частки секунди.
mgold

1
І це заплутано, оскільки це не працює таким чином у більшості систем Linux, оскільки: freddy @ hades ~% date --help | grep - -r -r, --reference = ФАЙЛ відображає час останньої модифікації FILE
frank42

1
хоча коментарі до цієї відповіді вірні, це не вина Рафи, і вони не зменшують його відповіді.
Майк

29

Ця версія схожа на відповідь чіборга , але вона виключає потребу у зовнішньому 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

+1: дуже повна відповідь, і я думаю, що дата швидша, ніж гаук.
Бруно Брант

@Bruno, як ти знаєш, дата швидше, ніж gawk.?
ghostdog74

3
@Bruno, @ ghostdog74: У моїй системі gawk(дуже приблизно) на 15% швидше, ніж dateу тимчасовому forциклі, що складається лише з gawk 'BEGIN { print strftime("%c", 1256571985); }'або date -d '@1256571985' +%cз виводу, переспрямованого на /dev/null.
Призупинено до подальшого повідомлення.

1
дата для мене незначно (на 5%) швидша, ніж gawk (mac osx 10.9.2, дата 8.23, gawk 4.1.1), але реальна перевага (g) awk полягає в тому, щоб прийняти трубу стовпчика багатьох часових позначок (див. моя відповідь нижче), що робить сценарій, наприклад, 250 разів швидшим за 1000 часових позначок.
webb

3
Зауважте, що моя відповідь відповідає вимогам ОП, зазначеним у запитанні, але прийнята відповідь ні.
Призупинено до подальшого повідомлення.

17

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

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

або

$ date -ud @1267619929

10

Ви можете використовувати цей простий сценарій awk:

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

Використання зразка:

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

Це не відповідає першому використанню - іноді я не хочу повторювати TS і використовувати натомість параметр.
чиборг

У певній старій версії зайнятих date -s @не працює, і awkвсе ще працює! Приклад без stdin також буде корисним.
Віктор Сергієнко

8

Оскільки Bash 4.2 ви можете використовувати printf«S %(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

Я використовую це під час перетворення файлів журналів або моніторингу їх:

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

саме те, що я шукав, можна скоротити доawk '{ printf strftime("%c: ", $1); $1 = ""; print $0; }'
ChrisWue

5

У OSX або BSD є еквівалентний -rпрапор, який, мабуть, приймає часову позначку unix. Ось приклад, який проводить дату чотири рази: один раз для першого побачення, щоб показати, що це таке; один для перетворення в часову позначку unix з %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

Якщо у вас вже є значення часової позначки, і вам просто потрібно знайти еквівалентну дату, в OS X ви можете просто ввести це в командному рядку: дата -r 1509453417
Ноель Вітмор

1
Це правда. Якщо ви подивитесь на мою відповідь, я насправді це демонструю.
Даніель Фаррелл

5

Ви можете отримати відформатовану дату з такої позначки часу, як ця

date +'%Y-%m-%d %H:%M:%S' -d "@timestamp"

Інакше: дата -ud "@ 1585667718" + '% Y-% m-% d% H:% M:% S'
AndiAna


3

У цій відповіді я копіюю відповідь Денніса Вільямсона і трохи модифікую її, щоб дозволити значне збільшення швидкості під час передавання стовпчика багатьох часових позначок до сценарію. Наприклад, трубопровід 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

2

приклад:

$ дата
Чт 22 березня 16:47:06 CST 2016

$ date -d "Четвер 22 березня 16:47:06 CST 2016" "+% s"
1458636426

$ date +% s
1458636453

$ date -d @ 1458636426
Чт 22 березня 16:47:06 CST 2016

$ date --date = '@ 1458636426'
Чт 22 березня 16:47:06 CST 2016



2

Я використовую цей міжплатформенний однолінійний:

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

Він повинен працювати як в macOS, так і в пізніших версіях поширених дистрибутивів Linux.


0

Наступний скрипт перетворює часові позначки довжиною 13 у рядку на еквівалентну дату у вашому локальному часовому поясі, використовуючи 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"

вхід

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

вихід

$ 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"}

-8

В PHP

$unix_time = 1256571985;

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

5
Приємно, але я просто хотів використовувати bash.
чиборг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.