時間・時刻処理について(1)

このエントリーをはてなブックマークに追加

前回は概念の話だけでしたが、今回からソースを交えた通常の解説に戻ります。
時間はプログラマが良く使う機能の1つでしょう。ベンチマークや経過時間の表示、データベースに時間を保存するなどなど。
時間については精度の違い等によりいくつかの種類があります。ここでは標準関数を使用して時間の取得・作成方法について解説していきます。

時間の取得

時間を取得・生成する関数

まずは時間の取得方法から。標準関数では以下の3種類が用意されています。

関数名説明
clock(3)プロセッサ時間の取得
time(2)time_t型で現在時間を取得(UTC)
mktime(3)struct tm型からtime_t型へ変換


clock(3)

clock(3)はプロセッサ時間を取るだけですので、現在時間を取得できません。何に使うかというと時間間隔を求めることです。 注意事項として、clock_tから秒を求めるにはCLOCKS_PER_SECで割る必要があります。

//clock.c
#include <stdio.h>
#include <time.h>

int main(void)
{
	clock_t start, end;
	long l;

	start = clock();

	//何か処理

	end = clock();
	printf("%f\n", (double)(end - start) / CLOCKS_PER_SEC);

	return 0;
}

実行すると経過時間が表示されます。sleep(3)関数などを使って実験するのが分かり易いかもしれません。

$ gcc -o clock clock.c
$ ./clock
0.130000

time(2)

次はtime(2)です。使い方は非常に簡単です。呼び出すと現在時間をtime_t型で返します。当然ですが時間精度は秒です。
ただしtime_t型のままでは表示が出来ません。正しい表示方法に関してはページの都合上次回に解説します。

//time.c
#include <stdio.h>
#include <time.h>

int main(void)
{
	time_t t;

	t = time(NULL);
	printf("%ld\n", t); //本当はprintfを使ったらダメ!!

	return 0;
}

コンパイルと実行すると整数値が得られます。これがエポックタイムからの秒数となります。

$ gcc -o time time.c
$ ./time
1009810800

mktime(3)

mktime(3)はstruct tm型からtime_t型(time(2)が作成するのと同じ型)を作成します。
struct tm型は以下のように定義されていて、時分秒等の値を別々で持っている型です。分かり易く言えばユーザが時間を指定して作成する関数です。
手元でstruct tm型の定義を確認したい場合は、"man asctime"で確認できます。Web上だとJM:asctime等で確認できます。

#include <time.h>
struct tm {
    int tm_sec;         /* 秒 */
    int tm_min;         /* 分 */
    int tm_hour;        /* 時間 */
    int tm_mday;        /* 日 */
    int tm_mon;         /* 月 */
    int tm_year;        /* 年 */
    int tm_wday;        /* 曜日 */
    int tm_yday;        /* 年内通算日 */
    int tm_isdst;       /* 夏時間 */
};

では、mktime(3)を使用してみます。

//mktime.c
#include <stdio.h>
#include <string.h>
#include <time.h>

int main(void)
{
	time_t t;
	struct tm m;

	memset(&pm, 0, sizeof(struct tm));

	//2012/1/1 00:00:00
	m.tm_year = 102; //2012年 1900年からの経過年月
	m.tm_mon = 0;
	m.tm_mday = 1;
	m.tm_hour = 0;
	m.tm_min = 0;
	m.tm_sec = 0;
	m.tm_isdst = 0; //夏時間は無効

	t = mktime(&m);
	printf("%ld\n", t); //本当はprintfを使ったらダメ!!

	return 0;
}

実行すると、time_tに変換できているのが分かります。

$ gcc -o mktime mktime.c
$ ./mktime
1009810800

まとめ

いかがだったでしょうか? 時間間隔を計算する関数や時間取得・生成関数を紹介しましたが、time_t型が秒で表されている為これだけでは実用的なプログラムは作れません。
そもそも本当はtime_t型はシステム側で宣言されている型なので、汎用性を考えればこの様にprintf(3)するのがそもそもまずいのですが...。

さて、次回はこのtime_tを文字列に変換したり、ローカルタイムへの変換等の解説をします。