シェルからエポックタイムスタンプを取得するPOSIX互換の方法は何ですか?

シェルからエポックタイムスタンプを取得するPOSIX互換の方法は何ですか?

私はPOSIXを見つけました。date%sまたは%N形式項目がないようです。だから私はそれらを使用することはできません。シェルスクリプトからエポックタイムスタンプを取得する別の方法は何ですか?

答え1

整数秒のエポック時間の場合、これは次のようになります。

awk 'BEGIN{srand(); print srand()}'

または:

awk 'BEGIN{print srand(srand())}'

〜のようにPOSIXではawksrand()パラメータがない場合は、現在の時間を疑似乱数ジェネレータのシードとして使用します。また、以前のシードを返すため、srand()上記の2番目のシードは以前のシードで使用されたエポック時間を返します。

以下を使用して小数部を取得できます。

echo|LC_ALL=C TZ=UTC0 diff -u /dev/null - |sed -n '2s/.*\(\.[0-9]*\).*/\1/p'

POSIXは出力フォーマットを指定しますdiff -u、ファイルがある場合は現在時刻を使用してください-

ただし、出力を受信する前に呼び出されてから数千または数百万ナノ秒が経過した可能性があり、同じ秒ではない可能性がありawkます。ただし、次のもの<epochtime> % 60と比較して、これが真であることを確認できます。第二diff必要に応じて、ヘッダーで(UTC)タイムスタンプの一部にすることができます。


1このawkソリューションに関して、POSIXは過去にこれを表現するために多くの言語を使用していないことに注意してください。私がやった異議申し立てしばらく前に、POSIXの不明瞭な表現について尋ねられ、実装にそのような過酷なエントロピーソースを使用することを強制することは今日では不合理であると指摘しました。逆に、解決するsrand()エポック時間を使用するための明示的な要件です。

答え2

time()結果を呼び出して印刷するCプログラムを作成します。サンプルプログラムのレンタルtime()機能仕様、たとえば、次のように呼び出しますseconds.c

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int main(void)
{
    time_t t = time(NULL);
    printf("%ju\n", (uintmax_t) t);
    return 0;
}

そしてc99 -o seconds seconds.c。 (読むと仕様そうですね。これがコンパイルする標準的な方法でなければなりません。 )


または、分解された日付を取得して秒を計算することもできます。 1日の長さは86400秒なので、これは比較的簡単です。シェル操作がそれを8進数として扱わないように、いくつかの値から先行ゼロを削除する必要があります。

シェル関数として:

epochtime() {
    eval "$(date -u +'y=%Y j=%j h=%H m=%M s=%S')"
    s=${s#0}
    m=${m#0}
    h=${h#0}
    j=${j#0}
    j=${j#0}
    t=$(( ((y-1970)*365 + (y-1969)/4 + j - 1)*86400 + h*3600 + m*60 + s))
    echo "$t"
}

うるう年の計算に関する注意:新起源以降の最初のうるう年は1972年で、(1972-1969)/4 = 3/4 = 0、そして(1973-1969)/ 4 = 4/4 = 1(整数切り捨てによる相違)))。したがって、(年-1969)/4はうるう年の数を表します。今後今年。今年のうるう日は、%j「年中の日」の値に含まれます。数字は1から計算され始めますが、経過した日数全体が必要なため、式に負数1が必要です。

答え3

dateエポックの後数秒間、POSIX式のシェル算術式を生成するカスタム書式文字列を使用してこれを実行できます。

secs=$((`TZ=GMT0 date \
+"((%Y-1600)*365+(%Y-1600)/4-(%Y-1600)/100+(%Y-1600)/400+1%j-1000-135140)\
*86400+(1%H-100)*3600+(1%M-100)*60+(1%S-100)"`))

この方法は次のとおりです。https://www.etalabs.net/sh_tricks.html

関連情報