時刻の扱い(1)

 UNIX系システムの時刻情報の考え方はとても単純です.
それはどのようなものかというと,
 
「”西暦1970年1月1日0時0分0秒”を基準として,その後の秒数で時刻を表現する」
 
というものです.そして各種の関数を呼び出すことで,
秒数で表現された時刻情報から,
年,月,日,曜日,時,分,秒などの情報を取得することになります.
 
また,日付や時,分,秒の値を保持するための各種の構造体も
提供されています.
 
■ システムの現在時刻の取得(秒単位)
 OSの現在時刻(秒単位)を取得するには time 関数を使います.
 
例.

time_t    t;
t = time(NULL);

上の例のようにすると,t の中に現在時刻が秒数として得られます.
 
日付や時分秒の情報を格納する構造体として tm があり,
localtime 関数や gmtime 関数を使用することで
time_t 型のデータから tm の各メンバに情報を与えることができます.
 
例.

time_t    t;
struct tm *jst;
t = time(NULL);
jst = localtime(&t);

上の例のようにすることで,t の値から日付や時分秒の数値を算出して
それを jst の各メンバに格納します.
localtime 関数はOSのタイムゾーンに合った形で日付と時刻を取得します.
また類似の関数に gmtime というものがあり,これを用いると
グリニッジ標準時の形式で日付と時刻を取得することができます.
 
ちなみに,構造体 tm の中身(定義)は下記のようなものです.

struct tm {
	int tm_sec;        /* 秒 (0-60) */
	int tm_min;        /* 分 (0-59) */
	int tm_hour;       /* 時間 (0-23) */
	int tm_mday;       /* 月内の日付 (1-31) */
	int tm_mon;        /* 月 (0-11) */
	int tm_year;       /* 年 - 1900 */
	int tm_wday;       /* 曜日 (0-6, 日曜 = 0) */
	int tm_yday;       /* 年内通算日 (0-365, 1 月 1 日 = 0) */
	int tm_isdst;      /* 夏時間 */
};

この後,jst->tm_year を参照することで,西暦年(下2桁)の数値を得ることができます.
 
便利な関数として strftime というものがあり,これを使用することで,
日付や時刻を表現する文字列を得ることができます.
例.現在の日付と時刻を1秒感覚で表示するプログラム

#include	<stdio.h>
#include	<time.h>
 
int main()
{
	time_t	t;
	struct	tm	*gmt, *jst;
	int	s1, s2;
	char	fgmt[128], fjst[128];
 
	s2 = 0;
	while ( -1 ) {
//		t = time(NULL);
		time(&t);
		gmt = gmtime( &t );
		jst = localtime( &t );
		s1 = gmt->tm_sec;
		if ( s1 != s2 ) {
			strftime(fgmt,sizeof(fgmt),"%Y/%m/%d(%a) %H:%M:%S",gmt);
			strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S(%a)",jst);
			printf("%s [%s]\n",fgmt,fjst);
			s2 = s1;
		}
	}
}

実行結果の例.

$ s_time
2015/03/16(Mon) 10:56:34 [2015/03/16(Mon) 19:56:34(Mon)]
2015/03/16(Mon) 10:56:35 [2015/03/16(Mon) 19:56:35(Mon)]
2015/03/16(Mon) 10:56:36 [2015/03/16(Mon) 19:56:36(Mon)]
2015/03/16(Mon) 10:56:37 [2015/03/16(Mon) 19:56:37(Mon)]
2015/03/16(Mon) 10:56:38 [2015/03/16(Mon) 19:56:38(Mon)]
2015/03/16(Mon) 10:56:39 [2015/03/16(Mon) 19:56:39(Mon)]
^C
$

 
■ システムの現在時刻の取得(ミリ秒単位)
 OSの現在時刻(ミリ秒単位)を取得するには ftime 関数を使います.
この関数を使用すると,秒とミリ秒の情報が構造体 timeb のメンバに格納されます.
 
例.10分の1秒毎に時刻の秒数を表示するプログラム

#include	<stdio.h>
#include	<sys/timeb.h>
 
struct	timeb	tb;
 
int main()
{
	int	sec,sec2, msec,msec2;
 
	ftime( &tb );
	sec2 = tb.time;
	msec2 = tb.millitm / 100;
	while ( -1 ) {
		ftime( &tb );
		sec = tb.time;
		msec = tb.millitm / 100;
		if ( msec != msec2 ) {
			printf("%d.%d\n",sec,msec);
			sec2 = sec;
			msec2 = msec;
		}
	}
}

 
localtime の逆関数
 tm 構造体の内容から,その時刻に対応する time_t の値を求めるには mktime 関数を使います.
 
例1.localtime で変換した tm 構造体の内容を time_t に逆変換する

#include	<stdio.h>
#include	<time.h>
 
int main()
{
	time_t	t;
	struct	tm	*jst;
	char	fjst[128];
 
//	t = time(NULL);
	time(&t);
	printf("Now, time_t is %ld\n",t);
 
	jst = localtime( &t );
	strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S(%a)",jst);
	printf("%s\n",fjst);
 
	t = mktime( jst );
	printf("mktime is      %ld\n",t);
}

実行例

$ s_mktime
Now, time_t is 1427529755
2015/03/28(Sat) 17:02:35(Sat)
mktime is      1427529755

 
例2.コマンドラインから入力した日付と時刻から time_t を求める

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include	<stdio.h>
#include	<time.h>
 
int main(ac,av)
int	ac;
char	**av;
{
	int	year, month, day, hour, min, sec;
	time_t	t;
	struct	tm	jst, *jst2;
	char	fjst[128];
 
	sscanf(av[1],"%d",&year);
	sscanf(av[2],"%d",&month);
	sscanf(av[3],"%d",&day);
	sscanf(av[4],"%d",&hour);
	sscanf(av[5],"%d",&min);
	sscanf(av[6],"%d",&sec);
	year  -= 1900;
	month -= 1;
 
	jst.tm_year   = year;
	jst.tm_mon    = month;
	jst.tm_mday   = day;
	jst.tm_hour   = hour;
	jst.tm_min    = min;
	jst.tm_sec    = sec;
	jst.tm_isdst  = -1;
 
	t = mktime(&jst);
	printf("%04d/%02d/%02d %02d:%02d:%02d\n",
			year+1900,month+1,day,hour,min,sec);
	printf("time_t is %ld\n",t);
 
	jst2 = localtime( &t );
	strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S",jst2);
	printf("%s\n",fjst);
 
	t = mktime( jst2 );
	printf("mktime is %ld\n",t);
}

実行結果の例

$ s_mktime2 2015 3 29 13 16 00
2015/03/29 13:16:00
time_t is 1427602560
2015/03/29(Sun) 13:16:00
mktime is 1427602560

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)