シェルスクリプトでエポック秒を得る

POSIXのシェルユーティリティにはエポック秒を直接出力するコマンドがないので生成する方法を考えます

perlを使う

POSIX非標準。perlぐらいどの*nixにもインストールされているしこれが普通。

$ perl -e 'print time, "\n"'

date(1)でフォーマット指定を使う

POSIX非標準。date(1)のフォーマット指定にエポック秒を出力する s があります。これはGNU拡張。

$ date +%s

日付時刻からエポック秒を計算する

全てPOSIXのコマンドだけでやろうとすると多分これしかないです。

エポック秒は次の計算式で算出出来ます。

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
http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap04.html#tag_04_14

というわけで、dateとawkを組み合わせて次のような感じになりました。日時出力時はUTCを指定するのを忘れない。

$ date -u '+%Y %j %H %M %S' |awk '{
	y = $1 - 1900;
	d = $2 - 1;
	t = $5 + $4*60 + $3*3600 + d*86400 + \
		(y-70)*31536000 + int((y-69)/4)*86400 - \
		int((y-1)/100)*86400 + int((y+299)/400)*86400;
	print t;
}'

Cで書く

エポック秒なんて time_t の値そのものなんだからバイナリ使えるなら time(2) 出力するだけでいいよねみたいな。なお、time_t を出力する時は intmax_t でキャストするのが良いらしいです。

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

int main(void) {
    printf("%jd\n", (intmax_t)time(NULL));
    return 0;
}