C言語 - 標準ライブラリ - time.h - time_t、struct tm を使用する(秒単位)

 
1. localtime_r 日時取得
2. strftime 日時 → 文字列
3. strptime 文字列 → 日時
4. time 日時取得
5. sleep 秒単位の実行停止

1. localtime_r 日時取得


struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
 localtime_r は localtime のスレッドセーフ版。  なので、localtime_r を使うようにすべきです。  timep の示す時間を struct tm 型に変換して返す。  struct tm 型は 以下の形式

struct tm {
        int     tm_sec;         //	秒	0~60(60 は閏秒)
        int     tm_min;         //	分	0~59
        int     tm_hour;        //	時	0~23
        int     tm_mday;        //	月内の日	0~31
        int     tm_mon;         //	1月を0とする月	0~11
        int     tm_year;        //	1900年を0とする年
        int     tm_wday;        //	日曜日を0とする曜日
        int     tm_yday;        //	1月1日を 0 とする日	0~365
        int     tm_isdst;       //	サマータイム
        long    tm_gmtoff;      //	グリニッジ時刻からのオフセット
        char    *tm_zone;       //	タイムゾーン
};
 通常、使用時は、後述の time と合わせて使用することになると思います。
#include <stdio.h>
#include <time.h>

int main(int argc, char *argv[])
{
	time_t now = time(NULL);

	struct tm stm = {};

	localtime_r(&now, &stm);

	printf("現在は %04d年%02d月%02d日 %02d:%02d:%02d です\n",
										stm.tm_year + 1900,
										stm.tm_mon,
										stm.tm_mday,
										stm.tm_hour,
										stm.tm_min,
										stm.tm_sec
										);
	return 0;
}

 というソースを書いて実行すると下記の結果が得られます。
現在は 2018年11月10日 12:49:14 です

2. strftime 日時 → 文字列


size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
 時刻 tm の内容を format で指定された書式指定にしたがって変換し、 長さ max の文字列 s に書き込む。  主な書式指定は以下の通り。
書式 意味
%d 0パディングした月内の日。01~31。
%H 0パディングした24時間表記の時。01~24。
%m 0パディングした2桁の月。01~12。
%M 0パディングした2桁の分。00~59。
%S 0パディングした2桁の秒。00~60。(60 は閏秒を考慮してのものらしい)
%Y 4桁の西暦年。

 下記のソースを書いて

#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

int main(int argc, char* argv[])
{
	char atime[PATH_MAX] = {};

	int i;

	time_t time1;

	struct tm	stm;

	for (i=0; i<5; i++)
	{
		time1 = time(NULL);

		localtime_r(&time1, &stm);

		strftime(atime, sizeof(atime), "%Y年%m月%d日 %H:%M:%S", &stm);

		printf("%s です\n", atime);
		sleep(1);
	}

	return 0;
}

 実行すると以下の結果が得られます。

> clang ソース名.c
> ./a.out
2018年06月16日 15:01:36 です
2018年06月16日 15:01:37 です
2018年06月16日 15:01:38 です
2018年06月16日 15:01:39 です
2018年06月16日 15:01:40 です

3. strptime 文字列 → 日時

 文字列で定義した日時を日時形式に変換します。

#include <time.h>

char *strptime(const char * restrict buf, const char * restrict format,
    										struct tm * restrict timeptr);
 下記のソースを書いて
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

int main(int argc, char* argv[])
{
	char atime[PATH_MAX] = {};

	struct tm	stm;

	strptime("2020年07月24日 12:34:59", "%Y年%m月%d日 %H:%M:%S", &stm);
	strftime(atime, sizeof(atime), "%Y年%m月%d日 %H:%M:%S", &stm);
	printf("%s\n", atime);

	memset(&stm, 0, sizeof(stm));
	strptime("12:34:59", "%H:%M:%S", &stm);
	strftime(atime, sizeof(atime), "%Y年%m月%d日 %H:%M:%S", &stm);
	printf("%s\n", atime);

	return 0;
}

 実行すると以下の結果が得られます。

> clang ソース名.c
> ./a.out
2020年07月24日 12:34:59
1900年01月00日 12:34:59
 2行目の出力結果が注目ですが・・・。  指定しなかった要素は0になるようです。  リターン値にも注意する必要があります。  説明によれば
 この関数の返り値は、関数の中で処理されなかった最初の文字へのポインターである。
 フォーマット文字列が必要する以上の文字が入力文字列に含まれている場合、 返り値は最後に処理された入力文字の次の文字を指す。
 すべての入力文字列が処理された場合、 返り値は文字列末尾のヌルバイトを指す。
 strptime() がフォーマット文字列のすべての比較に失敗し、 エラーが起こった場合、関数はヌルポインターを返す。
 ということで、失敗の場合、文字列は保証されませんので、戻り値が NULL でないことを確認しなければなりません。

4. time 日時取得


time_t time(time_t *t);
 現在時刻を 1970年1月1日 00:00:00 からの経過秒数で返す。  t が NULL でなければ、t の指す領域にも返します。

5. sleep 秒単位の実行停止


unsigned int sleep(unsigned int seconds);
 seconds で指定した秒数分、プロセスの実行を停止します。  指定秒数分停止後に戻る場合は、戻り値は 0 になります。  停止中にシグナルにより、プロセスの停止が中断されて実行状態になった場合は、戻り値には停止されなかった秒数の値が返ります。  精度が秒までなので、これ以上の実行停止を行うには、以降に紹介してある nanosleep を使用します。