it-swarm-ja.com

Unixタイムスタンプを人間が読める時間に変換する

最初の列にUnixタイムスタンプが含まれているawk/grepを含むテキストファイルを表示したいと思います。表示中に人間が読める時間に変換するにはどうすればよいですか?

16
TheRojam

行がUNIXタイムスタンプで始まる場合は、次のようにする必要があります。

Perl -pe 's/^(\d+)/localtime $1/e' inputfilename

Perl -pは、入力の各行に対して実行される-eで渡された式に対してループを呼び出し、ループの最後にバッファを出力します。

この式では、置換コマンドs///を使用して、各行の先頭で一連の数字を照合およびキャプチャし、UNIXタイムスタンプとして解釈されるこれらの数字のローカル時間表現に置き換えます。 /eは、置換パターンが式として評価されることを示します。

19
wurtel

AWKが Gawk の場合、strftimeを使用できます。

gawk '{ print strftime("%c", $1) }'

最初の列のタイムスタンプを現在のロケールのデフォルトの日付/時刻表現に変換します。

これを使用して、コンテンツを表示する前に変換できます。

gawk '{ print gensub($1, strftime("%c", $1), 1) }' inputfile
18
Stephen Kitt

ダンが彼の答えで言及している のように、Gnu date(1)コマンドには、出力される日付として扱う日付またはタイムスタンプを含む_-d_パラメーターを指定できます。 (ただし、これはPOSIXまたはBSDのdate(1)コマンドでは使用できません。)_@1571806800_は、_time_t_整数を指定するために使用される形式です。

フィルターとして機能するBashシェル関数を次に示します。入力から行を読み取り、すべての数字が行で始まるWordがタイムスタンプであると想定し、それを私の好きな形式の1つで人間が読める出力に変換します。

_ts2hr() {
    while read n rest; do
        if [[ $n =~ ^[0-9][0-9]*$ ]]; then
            echo "$(date -d @"$n" +"%Y-%m-%d %T")" "$rest"
        else
            echo "$n" "$rest"
        fi
    done
}
_

入力と出力は次のようになります。

_ts2hr <<____
1571806123 first line
# A comment?
1571720456 second date's here
Just a regular sentence.
1571547789 The last line.
____
2019-10-23 13:48:43 first line
# A comment?
2019-10-22 14:00:56 second date's here
Just a regular sentence.
2019-10-20 14:03:09 The last line.
_

必要に応じて関数を微調整して、必要な特定の入力および出力フォーマット、および使用可能なツールを処理できます。上記の関数がBashであるのは、主に_=~_演算子によってパターンマッチングが容易になったためです。 Bourne Shellでこれが必要な場合は、チェックを別の方法でコーディングする必要があります。

8
cjs

「日付」を使用

これには、Perl、awk、php、または長い算術式は必要ありません。 gnu "date"を使用してこれを行うことができます。これは、この種のことには本当に非常に役立ちます。 「日付」の他のバージョンの場合、YMMV。

$ date -d '1/1/1970 GMT 1571889039 seconds'
Wed Oct 23 20:50:39 PDT 2019

ここで起こっているのは、時間とその調整を指定しているということです。時間は、1970年1月1日、グリニッジ標準時、Unix Epochです。 (真夜中は明示的に指定されていません。時刻を省略した場合は常に暗黙的に使用されます。)

時間に157188​​9039秒の調整が追加されます。代わりに、タイムスタンプを使用してください。ドキュメントでは、この機能に「相対」という単語を使用しています。

より簡潔なバージョンがあり、マンページの例によってのみドキュメント化されています。これは、新しいバージョンのgnu dateで機能します。

$ date -d @2147483647
Mon Jan 18 19:14:07 PST 2038

日付を頻繁に操作する必要がある場合は、日付コマンドについて理解してください。それは単なる時計ではありません。シェルの日付/時刻ライブラリです。

5
Dan

これのポータブルバージョンでは、最悪の場合、自分で計算を実行できます。 Unixタイムスタンプは POSIX XBD 4.16秒からのエポック で定義されています:

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400

これはあなたが望むマッピングの逆なので、少しの作業* それを逆にするために必要です。これにより、「POSIX UTC」の詳細が表示されますが、現在のタイムゾーンでフォーマットする方法が必要になる場合があります。現れる date -dは移植性がないため、これを行うための適切な方法があるかどうかは不明です。

* Okそれは控えめな表現かもしれません。

GNUの日付がない場合、またはstrftimeまたは同等のプログラミング言語にアクセスできない場合は、自分で計算を行う必要があります。これは、コードゴルフの領域に入ります。

unix_to_iso_utc () {
    local day_unix=$(($1 / 86400))
    local day_offset=$(($1 % 86400))
    local d=$(($day_unix + 719468))
    local y=$((($d - ($d+2+3*$d/146097)/1461 + ($d-$d/146097)/36524 - ($d+1)/146097)/365))
    local y_d=$((365*$y + $y/4 - $y/100 + $y/400))
    local y_offset=$(($d - $y_d))
    local m=$((($y_offset - ($y_offset+20)/50) / 30))
    local m_d=$((30*$m + 3*($m+4)/5 - 2))
    local day=$(($y_offset - $m_d + 1))
    local m_cont=$((12*$y + $m + 2))
    local year=$(($m_cont/12))
    local month=$(($m_cont%12 + 1))
    local hour=$(($day_offset / 3600))
    local hour_offset=$(($day_offset % 3600))
    local minute=$(($hour_offset / 60))
    local second=$(($hour_offset % 60))
    DATE=$(printf "%04d-%02d-%02dT%02d:%02d:%02d" $year $month $day $hour $minute $second)
}

また、必要なものをハードコーディングできない限り、その時点ではおそらくタイムゾーンデータベースがないため、これは大きな実用上の問題になる可能性があります。

2
Teemu Kalvas

すでに述べたように、シェルやAWKを使用してこれを行うポータブルな方法は実際にはありません。 GAWKはそれを実行できますが、GAWK strftimeはAWKの特定のバージョン、つまりMAWKでは利用できません。また、MAWKは人気のあるディストリビューション(Debianなど)でも使用されます。

これには、ポータブルシェルまたはAWKソリューションが利用可能であることに同意します。しかし、そうではなく、おそらくおそらく何年もの間、そうなることはないでしょうが、最善の解決策は、プログラミング言語を使用することです。 Perlが提案されています。別のオプションはPHPです。

$ cat input.txt
1571806800 blue
1571720400 green
1571634000 orange
1571547600 red
1571461200 yellow

$ cat app.php
<?php
$r1 = fopen('input.txt', 'r');
while (true) {
   $s1 = fgets($r1);
   if ($s1 === false) {
      break;
   }
   $a1 = explode(' ', $s1);
   $n1 = + $a1[0];
   echo date(DATE_W3C, $n1), "\n";
}

$ php app.php
2019-10-23T05:00:00+00:00
2019-10-22T05:00:00+00:00
2019-10-21T05:00:00+00:00
2019-10-20T05:00:00+00:00
2019-10-19T05:00:00+00:00
1
Nine