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 |